@@ -15,6 +15,7 @@ import qualified Data.Set as S
1515import Control.Monad.State hiding (join)
1616import Data.Maybe
1717import Data.Either
18+import Data.Typeable (cast)
1819
1920--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
2021evalRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
@@ -22,11 +23,11 @@ evalRelationalExpr (RelationVariable name) = do
2223 relvarTable <- liftM relationVariables get
2324 return $ case M.lookup name relvarTable of
2425 Just res -> Right res
25− Nothing -> Left $ RelVarNotDefinedError name
26+ Nothing -> Left $ RelVarNotDefinedError name
2627
2728evalRelationalExpr (Project attrNames expr) = do
2829 rel <- evalRelationalExpr expr
29− case rel of
30+ case rel of
3031 Right rel2 -> return $ project attrNames rel2
3132 Left err -> return $ Left err
3233
@@ -47,71 +48,71 @@ evalRelationalExpr (Join exprA exprB) = do
4748 Right relA2 -> case relB of
4849 Left err -> return $ Left err
4950 Right relB2 -> return $ join relA2 relB2
50−
51+
5152evalRelationalExpr (MakeStaticRelation attributeSet tupleSet) = do
5253 case mkRelation attributeSet tupleSet of
5354 Right rel -> return $ Right rel
5455 Left err -> return $ Left err
55−
56+
5657evalRelationalExpr (ExistingRelation rel) = return (Right rel)
57−
58+
5859evalRelationalExpr (Rename oldAttrName newAttrName relExpr) = do
5960 evald <- evalRelationalExpr relExpr
6061 case evald of
6162 Right rel -> return $ rename oldAttrName newAttrName rel
6263 Left err -> return $ Left err
63−
64+
6465evalRelationalExpr (Group oldAttrNameSet newAttrName relExpr) = do
6566 evald <- evalRelationalExpr relExpr
66− case evald of
67+ case evald of
6768 Right rel -> return $ group oldAttrNameSet newAttrName rel
6869 Left err -> return $ Left err
69−
70+
7071evalRelationalExpr (Ungroup attrName relExpr) = do
7172 evald <- evalRelationalExpr relExpr
7273 case evald of
7374 Right rel -> return $ ungroup attrName rel
7475 Left err -> return $ Left err
75−
76+
7677evalRelationalExpr (Restrict predicateExpr relExpr) = do
7778 evald <- evalRelationalExpr relExpr
7879 context <- get
79− case evald of
80+ case evald of
8081 Left err -> return $ Left err
8182 Right rel -> case predicateRestrictionFilter context (attributes rel) predicateExpr of
8283 Left err -> return $ Left err
8384 Right filterfunc -> return $ restrict filterfunc rel
84−
85+
8586evalRelationalExpr (Equals relExprA relExprB) = do
8687 evaldA <- evalRelationalExpr relExprA
8788 evaldB <- evalRelationalExpr relExprB
8889 case evaldA of
8990 Left err -> return $ Left err
90− Right relA -> case evaldB of
91+ Right relA -> case evaldB of
9192 Left err -> return $ Left err
9293 Right relB -> return $ Right $ if relA == relB then relationTrue else relationFalse
93−
94+
9495--warning: copy-pasta from above- refactor
9596evalRelationalExpr (NotEquals relExprA relExprB) = do
9697 evaldA <- evalRelationalExpr relExprA
9798 evaldB <- evalRelationalExpr relExprB
9899 case evaldA of
99100 Left err -> return $ Left err
100− Right relA -> case evaldB of
101+ Right relA -> case evaldB of
101102 Left err -> return $ Left err
102103 Right relB -> return $ Right $ if relA /= relB then relationTrue else relationFalse
103−
104−-- extending a relation adds a single attribute with the results of the per-tuple expression evaluated
105−evalRelationalExpr (Extend tupleExpression relExpr) = do
104+
105+-- extending a relation adds a single attribute with the results of the per-tuple expression evaluated
106+evalRelationalExpr (Extend tupleExpression relExpr) = do
106107 evald <- evalRelationalExpr relExpr
107108 context <- get
108− case evald of
109+ case evald of
109110 Left err -> return $ Left err
110111 Right rel -> do
111112 case tupleExpressionProcessor rel tupleExpression context of
112113 Left err -> return $ Left err
113114 Right (newAttrs, tupProc) -> return $ relMogrify tupProc newAttrs rel
114−
115+
115116emptyDatabaseContext :: DatabaseContext
116117emptyDatabaseContext = DatabaseContext { inclusionDependencies = M.empty,
117118 relationVariables = M.empty,
@@ -126,8 +127,8 @@ basicDatabaseContext = DatabaseContext { inclusionDependencies = M.empty,
126127 }
127128
128129dateExamples :: DatabaseContext
129−dateExamples = DatabaseContext { inclusionDependencies = dateIncDeps,
130− relationVariables = M.union (relationVariables basicDatabaseContext) dateRelVars,
130+dateExamples = DatabaseContext { inclusionDependencies = dateIncDeps,
131+ relationVariables = M.union (relationVariables basicDatabaseContext) dateRelVars,
131132 atomFunctions = basicAtomFunctions}
132133 where
133134 dateRelVars = M.fromList [("S", suppliers),
@@ -141,77 +142,77 @@ dateExamples = DatabaseContext { inclusionDependencies = dateIncDeps,
141142 ("SP_pkey", simplePKey ["S#", "P#"] "SP")
142143 ]
143144 simplePKey attrNames relvarName = inclusionDependencyForKey (AttributeNames $ S.fromList attrNames) (RelationVariable relvarName)
144−
145−suppliersRel :: Relation
145+
146+suppliersRel :: Relation
146147suppliersRel = case mkRelationFromList attrs atomMatrix of
147148 Left _ -> undefined
148149 Right rel -> rel
149150 where
150− attrs = A.attributesFromList [Attribute "S#" StringAtomType,
151− Attribute "SNAME" StringAtomType,
152− Attribute "STATUS" IntAtomType,
153− Attribute "CITY" StringAtomType]
151+ attrs = A.attributesFromList [Attribute "S#" stringAtomType,
152+ Attribute "SNAME" stringAtomType,
153+ Attribute "STATUS" intAtomType,
154+ Attribute "CITY" stringAtomType]
154155 atomMatrix = [
155− [StringAtom "S1", StringAtom "Smith", IntAtom 20, StringAtom "London"],
156− [StringAtom "S2", StringAtom "Jones", IntAtom 10, StringAtom "Paris"],
157− [StringAtom "S3", StringAtom "Blake", IntAtom 30, StringAtom "Paris"],
158− [StringAtom "S4", StringAtom "Clark", IntAtom 20, StringAtom "London"],
159− [StringAtom "S5", StringAtom "Adams", IntAtom 30, StringAtom "Athens"]]
160−
156+ [stringAtom "S1", stringAtom "Smith", intAtom 20, stringAtom "London"],
157+ [stringAtom "S2", stringAtom "Jones", intAtom 10, stringAtom "Paris"],
158+ [stringAtom "S3", stringAtom "Blake", intAtom 30, stringAtom "Paris"],
159+ [stringAtom "S4", stringAtom "Clark", intAtom 20, stringAtom "London"],
160+ [stringAtom "S5", stringAtom "Adams", intAtom 30, stringAtom "Athens"]]
161+
161162supplierProductsRel :: Relation
162163supplierProductsRel = case mkRelationFromList attrs matrix of
163164 Left _ -> undefined
164165 Right rel -> rel
165166 where
166− attrs = A.attributesFromList [Attribute "S#" StringAtomType,
167− Attribute "P#" StringAtomType,
168− Attribute "QTY" IntAtomType]
167+ attrs = A.attributesFromList [Attribute "S#" stringAtomType,
168+ Attribute "P#" stringAtomType,
169+ Attribute "QTY" intAtomType]
169170 matrix = [
170− [StringAtom "S1", StringAtom "P1", IntAtom 300],
171− [StringAtom "S1", StringAtom "P2", IntAtom 200],
172− [StringAtom "S1", StringAtom "P3", IntAtom 400],
173− [StringAtom "S1", StringAtom "P4", IntAtom 200],
174− [StringAtom "S1", StringAtom "P5", IntAtom 100],
175− [StringAtom "S1", StringAtom "P6", IntAtom 100],
176− [StringAtom "S2", StringAtom "P1", IntAtom 300],
177− [StringAtom "S2", StringAtom "P2", IntAtom 400],
178− [StringAtom "S3", StringAtom "P2", IntAtom 200],
179− [StringAtom "S4", StringAtom "P2", IntAtom 200],
180− [StringAtom "S4", StringAtom "P4", IntAtom 300],
181− [StringAtom "S4", StringAtom "P5", IntAtom 400]
171+ [stringAtom "S1", stringAtom "P1", intAtom 300],
172+ [stringAtom "S1", stringAtom "P2", intAtom 200],
173+ [stringAtom "S1", stringAtom "P3", intAtom 400],
174+ [stringAtom "S1", stringAtom "P4", intAtom 200],
175+ [stringAtom "S1", stringAtom "P5", intAtom 100],
176+ [stringAtom "S1", stringAtom "P6", intAtom 100],
177+ [stringAtom "S2", stringAtom "P1", intAtom 300],
178+ [stringAtom "S2", stringAtom "P2", intAtom 400],
179+ [stringAtom "S3", stringAtom "P2", intAtom 200],
180+ [stringAtom "S4", stringAtom "P2", intAtom 200],
181+ [stringAtom "S4", stringAtom "P4", intAtom 300],
182+ [stringAtom "S4", stringAtom "P5", intAtom 400]
182183 ]
183−
184−productsRel :: Relation
184+
185+productsRel :: Relation
185186productsRel = case mkRelationFromList attrs matrix of
186187 Left _ -> undefined
187188 Right rel -> rel
188189 where
189− attrs = A.attributesFromList [Attribute "P#" StringAtomType,
190− Attribute "PNAME" StringAtomType,
191− Attribute "COLOR" StringAtomType,
192− Attribute "WEIGHT" IntAtomType,
193− Attribute "CITY" StringAtomType]
194− matrix = [
195− [StringAtom "P1", StringAtom "Nut", StringAtom "Red", IntAtom 12, StringAtom "London"],
196− [StringAtom "P2", StringAtom "Bolt", StringAtom "Green", IntAtom 17, StringAtom "Paris"],
197− [StringAtom "P3", StringAtom "Screw", StringAtom "Blue", IntAtom 17, StringAtom "Oslo"],
198− [StringAtom "P4", StringAtom "Screw", StringAtom "Red", IntAtom 14, StringAtom "London"],
199− [StringAtom "P5", StringAtom "Cam", StringAtom "Blue", IntAtom 12, StringAtom "Paris"],
200− [StringAtom "P6", StringAtom "Cog", StringAtom "Red", IntAtom 19, StringAtom "London"]
190+ attrs = A.attributesFromList [Attribute "P#" stringAtomType,
191+ Attribute "PNAME" stringAtomType,
192+ Attribute "COLOR" stringAtomType,
193+ Attribute "WEIGHT" intAtomType,
194+ Attribute "CITY" stringAtomType]
195+ matrix = [
196+ [stringAtom "P1", stringAtom "Nut", stringAtom "Red", intAtom 12, stringAtom "London"],
197+ [stringAtom "P2", stringAtom "Bolt", stringAtom "Green", intAtom 17, stringAtom "Paris"],
198+ [stringAtom "P3", stringAtom "Screw", stringAtom "Blue", intAtom 17, stringAtom "Oslo"],
199+ [stringAtom "P4", stringAtom "Screw", stringAtom "Red", intAtom 14, stringAtom "London"],
200+ [stringAtom "P5", stringAtom "Cam", stringAtom "Blue", intAtom 12, stringAtom "Paris"],
201+ [stringAtom "P6", stringAtom "Cog", stringAtom "Red", intAtom 19, stringAtom "London"]
201202 ]
202−
203−--helper function to process relation variable creation/assignment
203+
204+--helper function to process relation variable creation/assignment
204205setRelVar :: RelVarName -> Relation -> DatabaseState (Maybe RelationalError)
205−setRelVar relVarName rel = do
206+setRelVar relVarName rel = do
206207 currentContext <- get
207208 let newRelVars = M.insert relVarName rel $ relationVariables currentContext
208209 let potentialContext = DatabaseContext (inclusionDependencies currentContext) newRelVars (atomFunctions currentContext)
209210 case checkConstraints potentialContext of
210211 Just err -> return $ Just err
211− Nothing -> do
212+ Nothing -> do
212213 put potentialContext
213214 return Nothing
214−
215+
215216-- it is not an error to delete a relvar which does not exist, just like it is not an error to insert a pre-existing tuple into a relation
216217deleteRelVar :: RelVarName -> DatabaseState (Maybe RelationalError)
217218deleteRelVar relVarName = do
@@ -223,31 +224,31 @@ deleteRelVar relVarName = do
223224evalContextExpr :: DatabaseExpr -> DatabaseState (Maybe RelationalError)
224225evalContextExpr (Define relVarName attrs) = do
225226 relvars <- liftM relationVariables get
226− case M.member relVarName relvars of
227+ case M.member relVarName relvars of
227228 True -> return (Just (RelVarAlreadyDefinedError relVarName))
228229 False -> setRelVar relVarName emptyRelation
229230 where
230231 emptyRelation = Relation attrs emptyTupleSet
231−
232+
232233evalContextExpr (Undefine relVarName) = do
233234 deleteRelVar relVarName
234−
235+
235236evalContextExpr (Assign relVarName expr) = do
236237 -- in the future, it would be nice to get types from the RelationalExpr instead of needing to evaluate it
237238 relVarTable <- liftM relationVariables get
238239 let existingRelVar = M.lookup relVarName relVarTable
239− value <- evalRelationalExpr expr
240− case value of
240+ value <- evalRelationalExpr expr
241+ case value of
241242 Left err -> return $ Just err
242− Right rel -> case existingRelVar of
243+ Right rel -> case existingRelVar of
243244 Nothing -> setRelVar relVarName rel
244245 Just existingRel -> let expectedAttributes = attributes existingRel
245246 foundAttributes = attributes rel in
246− if A.attributesEqual expectedAttributes foundAttributes then
247+ if A.attributesEqual expectedAttributes foundAttributes then
247248 setRelVar relVarName rel
248249 else
249250 return $ Just (RelVarAssignmentTypeMismatchError expectedAttributes foundAttributes)
250−
251+
251252evalContextExpr (Insert relVarName relExpr) = evalContextExpr $ Assign relVarName (Union relExpr (RelationVariable relVarName))
252253
253254--assign empty rel until restriction is implemented
@@ -256,16 +257,16 @@ evalContextExpr (Delete relVarName predicate) = do
256257 case updatedRel of
257258 Left err -> return $ Just err
258259 Right rel -> setRelVar relVarName rel
259−
260+
260261--union of restricted+updated portion and the unrestricted+unupdated portion
261262evalContextExpr (Update relVarName attrAssignments restrictionPredicateExpr) = do
262263 currstate <- get
263− let relVarTable = relationVariables currstate
264+ let relVarTable = relationVariables currstate
264265 case M.lookup relVarName relVarTable of
265266 Nothing -> return $ Just (RelVarNotDefinedError relVarName)
266267 Just rel -> case predicateRestrictionFilter currstate (attributes rel) restrictionPredicateExpr of
267268 Left err -> return $ Just err
268− Right predicateFunc -> do
269+ Right predicateFunc -> do
269270 case makeUpdatedRel rel of
270271 Left err -> return $ Just err
271272 Right updatedRel -> setRelVar relVarName updatedRel
@@ -289,8 +290,8 @@ evalContextExpr (AddInclusionDependency newDepName newDep) = do
289290 Nothing -> do
290291 put potentialContext
291292 return Nothing
292−
293−evalContextExpr (RemoveInclusionDependency depName) = do
293+
294+evalContextExpr (RemoveInclusionDependency depName) = do
294295 currContext <- get
295296 let currDeps = inclusionDependencies currContext
296297 newDeps = M.delete depName currDeps
@@ -307,13 +308,13 @@ evalContextExpr (MultipleExpr exprs) = do
307308 case catMaybes evald of
308309 [] -> return $ Nothing
309310 err:_ -> return $ Just err
310−
311−-- restrict relvar to get affected tuples, update tuples, delete restriction from relvar, relvar = relvar union updated tuples
311+
312+-- restrict relvar to get affected tuples, update tuples, delete restriction from relvar, relvar = relvar union updated tuples
312313--evalRelVarExpr (Update relVarName updateMap) = do
313314
314315--run verification on all constraints
315316checkConstraints :: DatabaseContext -> Maybe RelationalError
316−checkConstraints context = case failures of
317+checkConstraints context = case failures of
317318 [] -> Nothing
318319 l:_ -> Just l
319320 where
@@ -321,13 +322,13 @@ checkConstraints context = case failures of
321322 deps = inclusionDependencies context
322323 eval expr = runState (evalRelationalExpr expr) context
323324 checkIncDep depName (InclusionDependency subsetExpr supersetExpr) = case evaldSub of
324− (Left err, _) -> Just err
325+ (Left err, _) -> Just err
325326 (Right relSub, _) -> case evaldSuper of
326327 (Left err, _) -> Just err
327328 (Right relSuper, _) -> case union relSub relSuper of
328329 Left err -> Just err
329− Right resultRel -> if resultRel == relSuper then
330− Nothing
330+ Right resultRel -> if resultRel == relSuper then
331+ Nothing
331332 else
332333 Just $ InclusionDependencyCheckError depName
333334 where
@@ -339,32 +340,32 @@ checkConstraint :: InclusionDependency -> DatabaseState (Maybe RelationalError)
339340checkConstraint (InclusionDependency name subDep superDep) = do
340341 evalSub <- evalRelationalExpr subDep
341342 evalSuper <- evalRelationalExpr superDep
342− case evalSub of
343+ case evalSub of
343344 Left err -> Just err
344− Right relSub
345+ Right relSub
345346 result <- liftM2 union evalSub evalSuper
346347 return $ Nothing
347348-}
348−
349+
349350-- the type of a relational expression is equal to the relation attribute set returned from executing the relational expression; therefore, the type can be cheaply derived by evaluating a relational expression and ignoring and tuple processing
350351-- furthermore, the type of a relational expression is the resultant header of the evaluated empty-tupled relation
351−
352+
352353typeForRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
353354typeForRelationalExpr expr = do
354355 currstate <- get
355356 --replace the relationVariables context element with a cloned set of relation devoid of tuples
356357 put $ contextWithEmptyTupleSets currstate
357358 evalRelationalExpr expr
358−
359−--returns a database context with all tuples removed
359+
360+--returns a database context with all tuples removed
360361--this is useful for type checking and optimization
361362contextWithEmptyTupleSets :: DatabaseContext -> DatabaseContext
362363contextWithEmptyTupleSets contextIn = DatabaseContext incDeps relVars funcs
363364 where
364− incDeps = inclusionDependencies contextIn
365+ incDeps = inclusionDependencies contextIn
365366 relVars = M.map (\rel -> Relation (attributes rel) emptyTupleSet) (relationVariables contextIn)
366367 funcs = atomFunctions contextIn
367−
368+
368369{- used for restrictions- take the restrictionpredicate and return the corresponding filter function -}
369370predicateRestrictionFilter :: DatabaseContext -> Attributes -> RestrictionPredicateExpr -> Either RelationalError (RelationTuple -> Bool)
370371predicateRestrictionFilter context attrs (AndPredicate expr1 expr2) = do
@@ -376,9 +377,9 @@ predicateRestrictionFilter context attrs (OrPredicate expr1 expr2) = do
376377 expr1v <- predicateRestrictionFilter context attrs expr1
377378 expr2v <- predicateRestrictionFilter context attrs expr2
378379 return $ \x -> expr1v x || expr2v x
379−
380+
380381predicateRestrictionFilter _ _ TruePredicate = Right $ \_ -> True
381−
382+
382383predicateRestrictionFilter context attrs (NotPredicate expr) = do
383384 exprv <- predicateRestrictionFilter context attrs expr
384385 return $ \x -> not (exprv x)
@@ -386,12 +387,12 @@ predicateRestrictionFilter context attrs (NotPredicate expr) = do
386387predicateRestrictionFilter context _ (RelationalExprPredicate relExpr) = case runState (evalRelationalExpr relExpr) context of
387388 (Left err, _) -> Left err
388389 (Right rel, _) -> if rel == relationTrue then
389− Right $ \_ -> True
390+ Right $ \_ -> True
390391 else if rel == relationFalse then
391− Right $ \_ -> False
392+ Right $ \_ -> False
392393 else
393394 Left $ PredicateExpressionError "Relational restriction filter must evaluate to 'true' or 'false'"
394−
395+
395396predicateRestrictionFilter context attrs (AttributeEqualityPredicate attrName atomExpr) = do
396397 attr <- A.attributeForName attrName attrs
397398 atomExprType <- typeFromAtomExpr attrs context atomExpr
@@ -400,20 +401,20 @@ predicateRestrictionFilter context attrs (AttributeEqualityPredicate attrName at
400401 else
401402 Right $ \tupleIn -> case atomForAttributeName attrName tupleIn of
402403 Left _ -> False
403− Right atomIn ->
404+ Right atomIn ->
404405 case evalAtomExpr tupleIn context atomExpr of
405406 Left _ -> False
406407 Right atomCmp -> atomCmp == atomIn
407−
408−-- in the future, it would be useful to do typechecking on the attribute and atom expr filters in advance
409−predicateRestrictionFilter context attrs (AtomExprPredicate atomExpr) = do
408+
409+-- in the future, it would be useful to do typechecking on the attribute and atom expr filters in advance
410+predicateRestrictionFilter context attrs (AtomExprPredicate atomExpr) = do
410411 aType <- typeFromAtomExpr attrs context atomExpr
411− if aType /= BoolAtomType then
412− Left $ AtomTypeMismatchError aType BoolAtomType
412+ if aType /= boolAtomType then
413+ Left $ AtomTypeMismatchError aType boolAtomType
413414 else
414415 Right (\tupleIn -> case evalAtomExpr tupleIn context atomExpr of
415416 Left _ -> False
416− Right boolAtomValue -> boolAtomValue == BoolAtom True)
417+ Right boolAtomValue -> boolAtomValue == Atom True)
417418
418419tupleExprCheckNewAttrName :: AttributeName -> Relation -> Either RelationalError Relation
419420tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName rel then
@@ -422,7 +423,7 @@ tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName
422423 Right rel
423424
424425tupleExpressionProcessor :: Relation -> TupleExpr -> DatabaseContext -> Either RelationalError (Attributes, RelationTuple -> RelationTuple)
425−tupleExpressionProcessor relIn
426+tupleExpressionProcessor relIn
426427 (AttributeTupleExpr newAttrName atomExpr) context = do
427428 _ <- tupleExprCheckNewAttrName newAttrName relIn
428429 atomExprType <- typeFromAtomExpr (attributes relIn) context atomExpr
@@ -445,12 +446,12 @@ evalAtomExpr tupIn context (FunctionAtomExpr funcName arguments) = do
445446 return $ (atomFunc func) evaldArgs
446447evalAtomExpr _ context (RelationAtomExpr relExpr) = do
447448 relAtom <- evalState (evalRelationalExpr relExpr) context
448− return $ RelationAtom relAtom
449+ return $ Atom relAtom
449450
450451typeFromAtomExpr :: Attributes -> DatabaseContext -> AtomExpr -> Either RelationalError AtomType
451452typeFromAtomExpr attrs _ (AttributeAtomExpr attrName) = A.atomTypeForAttributeName attrName attrs
452453typeFromAtomExpr _ _ (NakedAtomExpr atom) = Right (atomTypeForAtom atom)
453−typeFromAtomExpr _ context (FunctionAtomExpr funcName _) = do
454+typeFromAtomExpr _ context (FunctionAtomExpr funcName _) = do
454455 let funcs = atomFunctions context
455456 func <- atomFunctionForName funcName funcs
456457 return $ last (atomFuncType func)
@@ -481,49 +482,62 @@ verifyAtomExprTypes _ context (RelationAtomExpr relationExpr) expectedType = do
481482 (Left err, _) -> Left err
482483 (Right relType, _) -> atomTypeVerify expectedType (RelationAtomType (attributes relType))
483484
485+--not safe to use without upfront type-checking
486+castRelation :: Atom -> Relation
487+castRelation (Atom atom) = case cast atom of
488+ Just rel -> rel
489+ Nothing -> error "castRelation failure"
490+
491+unsafeCast :: (Atomable a) => Atom -> a
492+unsafeCast (Atom atom) = case cast atom of
493+ Just x -> x
494+ Nothing -> error "unsafeCast failed"
495+
484496basicAtomFunctions :: AtomFunctions
485497basicAtomFunctions = HS.fromList [
486498 --match on any relation type
487− AtomFunction "add" [IntAtomType, IntAtomType, IntAtomType] (\(i1:i2:_) -> (\(IntAtom a) (IntAtom b) -> IntAtom (a + b)) i1 i2),
499+ AtomFunction { atomFuncName = "add",
500+ atomFuncType = [intAtomType, intAtomType, intAtomType],
501+ atomFunc = (\(i1:i2:_) -> Atom $ ((unsafeCast i1)::Int) + unsafeCast i2)},
488502 AtomFunction { atomFuncName = "id",
489503 atomFuncType = [AnyAtomType, AnyAtomType],
490504 atomFunc = (\(x:_) -> x)},
491505 AtomFunction { atomFuncName = "sum",
492− atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
493− atomFunc = (\((RelationAtom relIn):_) -> relationSum relIn)},
506+ atomFuncType = foldAtomFuncType intAtomType intAtomType,
507+ atomFunc = (\(relAtom:_) -> relationSum $ unsafeCast relAtom)},
494508 AtomFunction { atomFuncName = "count",
495− atomFuncType = foldAtomFuncType AnyAtomType IntAtomType,
496− atomFunc = (\((RelationAtom relIn):_) -> relationCount relIn)},
509+ atomFuncType = foldAtomFuncType AnyAtomType intAtomType,
510+ atomFunc = (\((relIn):_) -> relationCount (castRelation relIn))},
497511 AtomFunction { atomFuncName = "max",
498− atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
499− atomFunc = (\((RelationAtom relIn):_) -> relationMax relIn)},
512+ atomFuncType = foldAtomFuncType intAtomType intAtomType,
513+ atomFunc = (\((relIn):_) -> relationMax (castRelation relIn))},
500514 AtomFunction { atomFuncName = "min",
501− atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
502− atomFunc = (\((RelationAtom relIn):_) -> relationMin relIn)},
515+ atomFuncType = foldAtomFuncType intAtomType intAtomType,
516+ atomFunc = (\((relIn):_) -> relationMin (castRelation relIn))},
503517 AtomFunction { atomFuncName = "lt",
504− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
518+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
505519 atomFunc = intAtomFuncLessThan False},
506520 AtomFunction { atomFuncName = "lte",
507− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
521+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
508522 atomFunc = intAtomFuncLessThan True},
509523 AtomFunction { atomFuncName = "gte",
510− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
524+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
511525 atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan False},
512526 AtomFunction { atomFuncName = "gt",
513− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
527+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
514528 atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan True},
515529 AtomFunction { atomFuncName = "not",
516− atomFuncType = [BoolAtomType, BoolAtomType],
530+ atomFuncType = [boolAtomType, boolAtomType],
517531 atomFunc = boolAtomNot}
518532 ]
519533
520534intAtomFuncLessThan :: Bool -> [Atom] -> Atom
521−intAtomFuncLessThan equality (iatom1:iatom2:_) = (\(IntAtom i1) (IntAtom i2) -> BoolAtom $ i1 `op` i2) iatom1 iatom2
535+intAtomFuncLessThan equality (iatom1:iatom2:_) = (\i1 i2 -> Atom $ ((unsafeCast i1)::Int) `op` unsafeCast i2) iatom1 iatom2
522536 where
523537 op = if equality then (<=) else (<)
524−intAtomFuncLessThan _ _= BoolAtom False
538+intAtomFuncLessThan _ _= Atom False
525539
526540boolAtomNot :: [Atom] -> Atom
527−boolAtomNot (BoolAtom bool:_) = BoolAtom $ not bool
528−boolAtomNot _ = BoolAtom False
541+boolAtomNot (bool:_) = Atom $ not (unsafeCast bool)
542+boolAtomNot _ = Atom False
529543