Haskell - represent a relationship (from database theory)

I am trying to write something that is equivalent to a relation in database theory.

-- A Relation has a name and a series of attributes. -- Each attribute might have a different type. data Relation = Relation String [Attribute] -- An Attribute has a name and a type data Attribute = Attribute String Type -- These three look like enough data Type = String | Integer | Fixed Int 

So, very good.

Now we want to redefine our attribute in order to have statements. Properties to be observed

 data Attribute a = Attribute String Type [Assersion a] data Assertion a where --Using GADTs LessThan :: Num a => a -> Assertion a Element :: Eq a => [a] -> Assertion a 

Now I need to add the type parameter to Relation, but this will make all attributes have the same type parameters in the statements. Thus, I could not have an integer attribute and a string attribute.

How to solve this problem?

+4
source share
1 answer

Nm has the right idea, provided that the relation should be a diagram of the relation, and not the relation itself. Here is an example of using Data.Typeable as a type class and TypeRep as a type representation. In addition, I want all types to be displayed as an example.

 -- Use Data.Typeable as our class of types import Data.Typeable data Relation = Relation String [Attribute] data Attribute = forall a. (Typeable a, Show a) => Attribute String (Proxy a) [Assertion a] -- Requires RankNTypes data Proxy a = Proxy data Assertion a where LessThan :: Ord a => a -> Assertion a Element :: Eq a => [a] -> Assertion a -- Requires GADTs -- Relation deriving instance Show Relation attributes (Relation _ x) = x -- Attribute deriving instance Show Attribute -- Requires StandaloneDeriving name (Attribute x _ _) = x validator :: Attribute -> forall a. (Typeable a) => a -> Maybe Bool validator (Attribute _ proxy assertions) value = (cast value) >>= \x -> Just $ all ((flip implementation) x) assertions dataType :: Attribute -> TypeRep dataType (Attribute _ proxy _) = getType proxy -- Proxy instance (Typeable a) => Show (Proxy a) where show = show . getType getType :: (Typeable a) => Proxy a -> TypeRep getType (_ :: Proxy a) = typeOf (undefined :: a) -- Requires ScopedTypeVariables -- Assertion deriving instance (Show a) => Show (Assertion a) implementation :: Assertion a -> a -> Bool implementation (LessThan y) x = x < y implementation (Element y) x = any ((==) x) y 

The example checks to see if a pair of values ​​are valid for various attribute attributes.

 -- Example explain :: (Typeable a, Show a) => a -> Attribute -> String explain value attribute = case validator attribute value of Nothing -> (show value) ++ " can't be a " ++ (name attribute) ++ " because it isn't a " ++ (show (dataType attribute)) Just False -> (show value) ++ " can't be a " ++ (name attribute) ++ " because it fails an assertion" Just True -> (show value) ++ " can be a " ++ (name attribute) main = do putStrLn $ show people sequence [ putStrLn (explain value attribute) | value <- [150 :: Int, 700], attribute <- attributes people ] sequence [ putStrLn (explain value attribute) | value <- ["Alice", "George"], attribute <- attributes people ] where people = Relation "People" [ Attribute "Name" (Proxy :: Proxy String) [Element ["Alice", "Bob", "Eve"] ], Attribute "Height" (Proxy :: Proxy Int) [LessThan 300] ] 

Here's the output of the program:

Relationship "People" [Attribute "Name" [Char] [Element ["Alice", "Bob", "Eve"]], Attribute "Height" Int [LessThan 300]]

150 cannot be a name because it is not [Char]

150 may be tall

700 cannot be a name because it is not [Char]

700 cannot be tall because it is not consistent with the statement

"Alice" may be the name

"Alice" cannot be tall because it is not int

"George" cannot be a name because he does not fulfill the statement

George can't be tall because it's not int

You can create your own class using your own representation of a smaller set of types, such as your data Type , and providing a different casting method.

+3
source

Source: https://habr.com/ru/post/1491897/


All Articles