@@ -15,6 +15,8 @@ import qualified Data.Set as S
1515import Control.Monad.State hiding (join)
1616import Data.Maybe
1717import Data.Either
18+import Data.Typeable (cast)
19+import qualified Data.Text as T
1820
1921--relvar state is needed in evaluation of relational expression but only as read-only in order to extract current relvar values
2022evalRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
@@ -22,11 +24,11 @@ evalRelationalExpr (RelationVariable name) = do
2224 relvarTable <- liftM relationVariables get
2325 return $ case M.lookup name relvarTable of
2426 Just res -> Right res
25− Nothing -> Left $ RelVarNotDefinedError name
27+ Nothing -> Left $ RelVarNotDefinedError name
2628
2729evalRelationalExpr (Project attrNames expr) = do
2830 rel <- evalRelationalExpr expr
29− case rel of
31+ case rel of
3032 Right rel2 -> return $ project attrNames rel2
3133 Left err -> return $ Left err
3234
@@ -47,71 +49,71 @@ evalRelationalExpr (Join exprA exprB) = do
4749 Right relA2 -> case relB of
4850 Left err -> return $ Left err
4951 Right relB2 -> return $ join relA2 relB2
50−
52+
5153evalRelationalExpr (MakeStaticRelation attributeSet tupleSet) = do
5254 case mkRelation attributeSet tupleSet of
5355 Right rel -> return $ Right rel
5456 Left err -> return $ Left err
55−
57+
5658evalRelationalExpr (ExistingRelation rel) = return (Right rel)
57−
59+
5860evalRelationalExpr (Rename oldAttrName newAttrName relExpr) = do
5961 evald <- evalRelationalExpr relExpr
6062 case evald of
6163 Right rel -> return $ rename oldAttrName newAttrName rel
6264 Left err -> return $ Left err
63−
65+
6466evalRelationalExpr (Group oldAttrNameSet newAttrName relExpr) = do
6567 evald <- evalRelationalExpr relExpr
66− case evald of
68+ case evald of
6769 Right rel -> return $ group oldAttrNameSet newAttrName rel
6870 Left err -> return $ Left err
69−
71+
7072evalRelationalExpr (Ungroup attrName relExpr) = do
7173 evald <- evalRelationalExpr relExpr
7274 case evald of
7375 Right rel -> return $ ungroup attrName rel
7476 Left err -> return $ Left err
75−
77+
7678evalRelationalExpr (Restrict predicateExpr relExpr) = do
7779 evald <- evalRelationalExpr relExpr
7880 context <- get
79− case evald of
81+ case evald of
8082 Left err -> return $ Left err
8183 Right rel -> case predicateRestrictionFilter context (attributes rel) predicateExpr of
8284 Left err -> return $ Left err
8385 Right filterfunc -> return $ restrict filterfunc rel
84−
86+
8587evalRelationalExpr (Equals relExprA relExprB) = do
8688 evaldA <- evalRelationalExpr relExprA
8789 evaldB <- evalRelationalExpr relExprB
8890 case evaldA of
8991 Left err -> return $ Left err
90− Right relA -> case evaldB of
92+ Right relA -> case evaldB of
9193 Left err -> return $ Left err
9294 Right relB -> return $ Right $ if relA == relB then relationTrue else relationFalse
93−
95+
9496--warning: copy-pasta from above- refactor
9597evalRelationalExpr (NotEquals relExprA relExprB) = do
9698 evaldA <- evalRelationalExpr relExprA
9799 evaldB <- evalRelationalExpr relExprB
98100 case evaldA of
99101 Left err -> return $ Left err
100− Right relA -> case evaldB of
102+ Right relA -> case evaldB of
101103 Left err -> return $ Left err
102104 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
105+
106+-- extending a relation adds a single attribute with the results of the per-tuple expression evaluated
107+evalRelationalExpr (Extend tupleExpression relExpr) = do
106108 evald <- evalRelationalExpr relExpr
107109 context <- get
108− case evald of
110+ case evald of
109111 Left err -> return $ Left err
110112 Right rel -> do
111113 case tupleExpressionProcessor rel tupleExpression context of
112114 Left err -> return $ Left err
113115 Right (newAttrs, tupProc) -> return $ relMogrify tupProc newAttrs rel
114−
116+
115117emptyDatabaseContext :: DatabaseContext
116118emptyDatabaseContext = DatabaseContext { inclusionDependencies = M.empty,
117119 relationVariables = M.empty,
@@ -126,8 +128,8 @@ basicDatabaseContext = DatabaseContext { inclusionDependencies = M.empty,
126128 }
127129
128130dateExamples :: DatabaseContext
129−dateExamples = DatabaseContext { inclusionDependencies = dateIncDeps,
130− relationVariables = M.union (relationVariables basicDatabaseContext) dateRelVars,
131+dateExamples = DatabaseContext { inclusionDependencies = dateIncDeps,
132+ relationVariables = M.union (relationVariables basicDatabaseContext) dateRelVars,
131133 atomFunctions = basicAtomFunctions}
132134 where
133135 dateRelVars = M.fromList [("S", suppliers),
@@ -141,77 +143,85 @@ dateExamples = DatabaseContext { inclusionDependencies = dateIncDeps,
141143 ("SP_pkey", simplePKey ["S#", "P#"] "SP")
142144 ]
143145 simplePKey attrNames relvarName = inclusionDependencyForKey (AttributeNames $ S.fromList attrNames) (RelationVariable relvarName)
144−
145−suppliersRel :: Relation
146+
147+--textAtom shortcut
148+tAtom :: T.Text -> Atom
149+tAtom t = Atom t
150+
151+--intAtom shortcut
152+iAtom ::Int -> Atom
153+iAtom i = Atom i
154+
155+suppliersRel :: Relation
146156suppliersRel = case mkRelationFromList attrs atomMatrix of
147157 Left _ -> undefined
148158 Right rel -> rel
149159 where
150− attrs = A.attributesFromList [Attribute "S#" StringAtomType,
151− Attribute "SNAME" StringAtomType,
152− Attribute "STATUS" IntAtomType,
153− Attribute "CITY" StringAtomType]
160+ attrs = A.attributesFromList [Attribute "S#" stringAtomType,
161+ Attribute "SNAME" stringAtomType,
162+ Attribute "STATUS" intAtomType,
163+ Attribute "CITY" stringAtomType]
154164 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−
165+ [tAtom "S1", tAtom "Smith", iAtom 20, tAtom "London"],
166+ [tAtom "S2", tAtom "Jones", iAtom 10, tAtom "Paris"],
167+ [tAtom "S3", tAtom "Blake", iAtom 30, tAtom "Paris"],
168+ [tAtom "S4", tAtom "Clark", iAtom 20, tAtom "London"],
169+ [tAtom "S5", tAtom "Adams", iAtom 30, tAtom "Athens"]]
170+
161171supplierProductsRel :: Relation
162172supplierProductsRel = case mkRelationFromList attrs matrix of
163173 Left _ -> undefined
164174 Right rel -> rel
165175 where
166− attrs = A.attributesFromList [Attribute "S#" StringAtomType,
167− Attribute "P#" StringAtomType,
168− Attribute "QTY" IntAtomType]
176+ attrs = A.attributesFromList [Attribute "S#" stringAtomType,
177+ Attribute "P#" stringAtomType,
178+ Attribute "QTY" intAtomType]
169179 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]
180+ [tAtom "S1", tAtom "P1", iAtom 300],
181+ [tAtom "S1", tAtom "P2", iAtom 200],
182+ [tAtom "S1", tAtom "P3", iAtom 400],
183+ [tAtom "S1", tAtom "P4", iAtom 200],
184+ [tAtom "S1", tAtom "P5", iAtom 100],
185+ [tAtom "S1", tAtom "P6", iAtom 100],
186+ [tAtom "S2", tAtom "P1", iAtom 300],
187+ [tAtom "S2", tAtom "P2", iAtom 400],
188+ [tAtom "S3", tAtom "P2", iAtom 200],
189+ [tAtom "S4", tAtom "P2", iAtom 200],
190+ [tAtom "S4", tAtom "P4", iAtom 300],
191+ [tAtom "S4", tAtom "P5", iAtom 400]
182192 ]
183−
184−productsRel :: Relation
193+
194+productsRel :: Relation
185195productsRel = case mkRelationFromList attrs matrix of
186196 Left _ -> undefined
187197 Right rel -> rel
188198 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"]
199+ attrs = A.attributesFromList [Attribute "P#" stringAtomType,
200+ Attribute "PNAME" stringAtomType,
201+ Attribute "COLOR" stringAtomType,
202+ Attribute "WEIGHT" intAtomType,
203+ Attribute "CITY" stringAtomType]
204+ matrix = [
205+ [tAtom "P1", tAtom "Nut", tAtom "Red", iAtom 12, tAtom "London"],
206+ [tAtom "P2", tAtom "Bolt", tAtom "Green", iAtom 17, tAtom "Paris"],
207+ [tAtom "P3", tAtom "Screw", tAtom "Blue", iAtom 17, tAtom "Oslo"],
208+ [tAtom "P4", tAtom "Screw", tAtom "Red", iAtom 14, tAtom "London"],
209+ [tAtom "P5", tAtom "Cam", tAtom "Blue", iAtom 12, tAtom "Paris"],
210+ [tAtom "P6", tAtom "Cog", tAtom "Red", iAtom 19, tAtom "London"]
201211 ]
202−
203−--helper function to process relation variable creation/assignment
212+
213+--helper function to process relation variable creation/assignment
204214setRelVar :: RelVarName -> Relation -> DatabaseState (Maybe RelationalError)
205−setRelVar relVarName rel = do
215+setRelVar relVarName rel = do
206216 currentContext <- get
207217 let newRelVars = M.insert relVarName rel $ relationVariables currentContext
208218 let potentialContext = DatabaseContext (inclusionDependencies currentContext) newRelVars (atomFunctions currentContext)
209219 case checkConstraints potentialContext of
210220 Just err -> return $ Just err
211− Nothing -> do
221+ Nothing -> do
212222 put potentialContext
213223 return Nothing
214−
224+
215225-- 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
216226deleteRelVar :: RelVarName -> DatabaseState (Maybe RelationalError)
217227deleteRelVar relVarName = do
@@ -223,31 +233,31 @@ deleteRelVar relVarName = do
223233evalContextExpr :: DatabaseExpr -> DatabaseState (Maybe RelationalError)
224234evalContextExpr (Define relVarName attrs) = do
225235 relvars <- liftM relationVariables get
226− case M.member relVarName relvars of
236+ case M.member relVarName relvars of
227237 True -> return (Just (RelVarAlreadyDefinedError relVarName))
228238 False -> setRelVar relVarName emptyRelation
229239 where
230240 emptyRelation = Relation attrs emptyTupleSet
231−
241+
232242evalContextExpr (Undefine relVarName) = do
233243 deleteRelVar relVarName
234−
244+
235245evalContextExpr (Assign relVarName expr) = do
236246 -- in the future, it would be nice to get types from the RelationalExpr instead of needing to evaluate it
237247 relVarTable <- liftM relationVariables get
238248 let existingRelVar = M.lookup relVarName relVarTable
239− value <- evalRelationalExpr expr
240− case value of
249+ value <- evalRelationalExpr expr
250+ case value of
241251 Left err -> return $ Just err
242− Right rel -> case existingRelVar of
252+ Right rel -> case existingRelVar of
243253 Nothing -> setRelVar relVarName rel
244254 Just existingRel -> let expectedAttributes = attributes existingRel
245255 foundAttributes = attributes rel in
246− if A.attributesEqual expectedAttributes foundAttributes then
256+ if A.attributesEqual expectedAttributes foundAttributes then
247257 setRelVar relVarName rel
248258 else
249259 return $ Just (RelVarAssignmentTypeMismatchError expectedAttributes foundAttributes)
250−
260+
251261evalContextExpr (Insert relVarName relExpr) = evalContextExpr $ Assign relVarName (Union relExpr (RelationVariable relVarName))
252262
253263--assign empty rel until restriction is implemented
@@ -256,16 +266,16 @@ evalContextExpr (Delete relVarName predicate) = do
256266 case updatedRel of
257267 Left err -> return $ Just err
258268 Right rel -> setRelVar relVarName rel
259−
269+
260270--union of restricted+updated portion and the unrestricted+unupdated portion
261271evalContextExpr (Update relVarName attrAssignments restrictionPredicateExpr) = do
262272 currstate <- get
263− let relVarTable = relationVariables currstate
273+ let relVarTable = relationVariables currstate
264274 case M.lookup relVarName relVarTable of
265275 Nothing -> return $ Just (RelVarNotDefinedError relVarName)
266276 Just rel -> case predicateRestrictionFilter currstate (attributes rel) restrictionPredicateExpr of
267277 Left err -> return $ Just err
268− Right predicateFunc -> do
278+ Right predicateFunc -> do
269279 case makeUpdatedRel rel of
270280 Left err -> return $ Just err
271281 Right updatedRel -> setRelVar relVarName updatedRel
@@ -289,8 +299,8 @@ evalContextExpr (AddInclusionDependency newDepName newDep) = do
289299 Nothing -> do
290300 put potentialContext
291301 return Nothing
292−
293−evalContextExpr (RemoveInclusionDependency depName) = do
302+
303+evalContextExpr (RemoveInclusionDependency depName) = do
294304 currContext <- get
295305 let currDeps = inclusionDependencies currContext
296306 newDeps = M.delete depName currDeps
@@ -307,13 +317,13 @@ evalContextExpr (MultipleExpr exprs) = do
307317 case catMaybes evald of
308318 [] -> return $ Nothing
309319 err:_ -> return $ Just err
310−
311−-- restrict relvar to get affected tuples, update tuples, delete restriction from relvar, relvar = relvar union updated tuples
320+
321+-- restrict relvar to get affected tuples, update tuples, delete restriction from relvar, relvar = relvar union updated tuples
312322--evalRelVarExpr (Update relVarName updateMap) = do
313323
314324--run verification on all constraints
315325checkConstraints :: DatabaseContext -> Maybe RelationalError
316−checkConstraints context = case failures of
326+checkConstraints context = case failures of
317327 [] -> Nothing
318328 l:_ -> Just l
319329 where
@@ -321,13 +331,13 @@ checkConstraints context = case failures of
321331 deps = inclusionDependencies context
322332 eval expr = runState (evalRelationalExpr expr) context
323333 checkIncDep depName (InclusionDependency subsetExpr supersetExpr) = case evaldSub of
324− (Left err, _) -> Just err
334+ (Left err, _) -> Just err
325335 (Right relSub, _) -> case evaldSuper of
326336 (Left err, _) -> Just err
327337 (Right relSuper, _) -> case union relSub relSuper of
328338 Left err -> Just err
329− Right resultRel -> if resultRel == relSuper then
330− Nothing
339+ Right resultRel -> if resultRel == relSuper then
340+ Nothing
331341 else
332342 Just $ InclusionDependencyCheckError depName
333343 where
@@ -339,32 +349,32 @@ checkConstraint :: InclusionDependency -> DatabaseState (Maybe RelationalError)
339349checkConstraint (InclusionDependency name subDep superDep) = do
340350 evalSub <- evalRelationalExpr subDep
341351 evalSuper <- evalRelationalExpr superDep
342− case evalSub of
352+ case evalSub of
343353 Left err -> Just err
344− Right relSub
354+ Right relSub
345355 result <- liftM2 union evalSub evalSuper
346356 return $ Nothing
347357-}
348−
358+
349359-- 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
350360-- furthermore, the type of a relational expression is the resultant header of the evaluated empty-tupled relation
351−
361+
352362typeForRelationalExpr :: RelationalExpr -> DatabaseState (Either RelationalError Relation)
353363typeForRelationalExpr expr = do
354364 currstate <- get
355365 --replace the relationVariables context element with a cloned set of relation devoid of tuples
356366 put $ contextWithEmptyTupleSets currstate
357367 evalRelationalExpr expr
358−
359−--returns a database context with all tuples removed
368+
369+--returns a database context with all tuples removed
360370--this is useful for type checking and optimization
361371contextWithEmptyTupleSets :: DatabaseContext -> DatabaseContext
362372contextWithEmptyTupleSets contextIn = DatabaseContext incDeps relVars funcs
363373 where
364− incDeps = inclusionDependencies contextIn
374+ incDeps = inclusionDependencies contextIn
365375 relVars = M.map (\rel -> Relation (attributes rel) emptyTupleSet) (relationVariables contextIn)
366376 funcs = atomFunctions contextIn
367−
377+
368378{- used for restrictions- take the restrictionpredicate and return the corresponding filter function -}
369379predicateRestrictionFilter :: DatabaseContext -> Attributes -> RestrictionPredicateExpr -> Either RelationalError (RelationTuple -> Bool)
370380predicateRestrictionFilter context attrs (AndPredicate expr1 expr2) = do
@@ -376,9 +386,9 @@ predicateRestrictionFilter context attrs (OrPredicate expr1 expr2) = do
376386 expr1v <- predicateRestrictionFilter context attrs expr1
377387 expr2v <- predicateRestrictionFilter context attrs expr2
378388 return $ \x -> expr1v x || expr2v x
379−
389+
380390predicateRestrictionFilter _ _ TruePredicate = Right $ \_ -> True
381−
391+
382392predicateRestrictionFilter context attrs (NotPredicate expr) = do
383393 exprv <- predicateRestrictionFilter context attrs expr
384394 return $ \x -> not (exprv x)
@@ -386,12 +396,12 @@ predicateRestrictionFilter context attrs (NotPredicate expr) = do
386396predicateRestrictionFilter context _ (RelationalExprPredicate relExpr) = case runState (evalRelationalExpr relExpr) context of
387397 (Left err, _) -> Left err
388398 (Right rel, _) -> if rel == relationTrue then
389− Right $ \_ -> True
399+ Right $ \_ -> True
390400 else if rel == relationFalse then
391− Right $ \_ -> False
401+ Right $ \_ -> False
392402 else
393403 Left $ PredicateExpressionError "Relational restriction filter must evaluate to 'true' or 'false'"
394−
404+
395405predicateRestrictionFilter context attrs (AttributeEqualityPredicate attrName atomExpr) = do
396406 attr <- A.attributeForName attrName attrs
397407 atomExprType <- typeFromAtomExpr attrs context atomExpr
@@ -400,20 +410,20 @@ predicateRestrictionFilter context attrs (AttributeEqualityPredicate attrName at
400410 else
401411 Right $ \tupleIn -> case atomForAttributeName attrName tupleIn of
402412 Left _ -> False
403− Right atomIn ->
413+ Right atomIn ->
404414 case evalAtomExpr tupleIn context atomExpr of
405415 Left _ -> False
406416 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
417+
418+-- in the future, it would be useful to do typechecking on the attribute and atom expr filters in advance
419+predicateRestrictionFilter context attrs (AtomExprPredicate atomExpr) = do
410420 aType <- typeFromAtomExpr attrs context atomExpr
411− if aType /= BoolAtomType then
412− Left $ AtomTypeMismatchError aType BoolAtomType
421+ if aType /= boolAtomType then
422+ Left $ AtomTypeMismatchError aType boolAtomType
413423 else
414424 Right (\tupleIn -> case evalAtomExpr tupleIn context atomExpr of
415425 Left _ -> False
416− Right boolAtomValue -> boolAtomValue == BoolAtom True)
426+ Right boolAtomValue -> boolAtomValue == Atom True)
417427
418428tupleExprCheckNewAttrName :: AttributeName -> Relation -> Either RelationalError Relation
419429tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName rel then
@@ -422,7 +432,7 @@ tupleExprCheckNewAttrName attrName rel = if isRight $ attributeForName attrName
422432 Right rel
423433
424434tupleExpressionProcessor :: Relation -> TupleExpr -> DatabaseContext -> Either RelationalError (Attributes, RelationTuple -> RelationTuple)
425−tupleExpressionProcessor relIn
435+tupleExpressionProcessor relIn
426436 (AttributeTupleExpr newAttrName atomExpr) context = do
427437 _ <- tupleExprCheckNewAttrName newAttrName relIn
428438 atomExprType <- typeFromAtomExpr (attributes relIn) context atomExpr
@@ -445,12 +455,12 @@ evalAtomExpr tupIn context (FunctionAtomExpr funcName arguments) = do
445455 return $ (atomFunc func) evaldArgs
446456evalAtomExpr _ context (RelationAtomExpr relExpr) = do
447457 relAtom <- evalState (evalRelationalExpr relExpr) context
448− return $ RelationAtom relAtom
458+ return $ Atom relAtom
449459
450460typeFromAtomExpr :: Attributes -> DatabaseContext -> AtomExpr -> Either RelationalError AtomType
451461typeFromAtomExpr attrs _ (AttributeAtomExpr attrName) = A.atomTypeForAttributeName attrName attrs
452462typeFromAtomExpr _ _ (NakedAtomExpr atom) = Right (atomTypeForAtom atom)
453−typeFromAtomExpr _ context (FunctionAtomExpr funcName _) = do
463+typeFromAtomExpr _ context (FunctionAtomExpr funcName _) = do
454464 let funcs = atomFunctions context
455465 func <- atomFunctionForName funcName funcs
456466 return $ last (atomFuncType func)
@@ -481,49 +491,62 @@ verifyAtomExprTypes _ context (RelationAtomExpr relationExpr) expectedType = do
481491 (Left err, _) -> Left err
482492 (Right relType, _) -> atomTypeVerify expectedType (RelationAtomType (attributes relType))
483493
494+--not safe to use without upfront type-checking
495+castRelation :: Atom -> Relation
496+castRelation (Atom atom) = case cast atom of
497+ Just rel -> rel
498+ Nothing -> error "castRelation failure"
499+
500+unsafeCast :: (Atomable a) => Atom -> a
501+unsafeCast (Atom atom) = case cast atom of
502+ Just x -> x
503+ Nothing -> error "unsafeCast failed"
504+
484505basicAtomFunctions :: AtomFunctions
485506basicAtomFunctions = HS.fromList [
486507 --match on any relation type
487− AtomFunction "add" [IntAtomType, IntAtomType, IntAtomType] (\(i1:i2:_) -> (\(IntAtom a) (IntAtom b) -> IntAtom (a + b)) i1 i2),
508+ AtomFunction { atomFuncName = "add",
509+ atomFuncType = [intAtomType, intAtomType, intAtomType],
510+ atomFunc = (\(i1:i2:_) -> Atom $ ((unsafeCast i1)::Int) + unsafeCast i2)},
488511 AtomFunction { atomFuncName = "id",
489512 atomFuncType = [AnyAtomType, AnyAtomType],
490513 atomFunc = (\(x:_) -> x)},
491514 AtomFunction { atomFuncName = "sum",
492− atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
493− atomFunc = (\((RelationAtom relIn):_) -> relationSum relIn)},
515+ atomFuncType = foldAtomFuncType intAtomType intAtomType,
516+ atomFunc = (\(relAtom:_) -> relationSum $ unsafeCast relAtom)},
494517 AtomFunction { atomFuncName = "count",
495− atomFuncType = foldAtomFuncType AnyAtomType IntAtomType,
496− atomFunc = (\((RelationAtom relIn):_) -> relationCount relIn)},
518+ atomFuncType = foldAtomFuncType AnyAtomType intAtomType,
519+ atomFunc = (\((relIn):_) -> relationCount (castRelation relIn))},
497520 AtomFunction { atomFuncName = "max",
498− atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
499− atomFunc = (\((RelationAtom relIn):_) -> relationMax relIn)},
521+ atomFuncType = foldAtomFuncType intAtomType intAtomType,
522+ atomFunc = (\((relIn):_) -> relationMax (castRelation relIn))},
500523 AtomFunction { atomFuncName = "min",
501− atomFuncType = foldAtomFuncType IntAtomType IntAtomType,
502− atomFunc = (\((RelationAtom relIn):_) -> relationMin relIn)},
524+ atomFuncType = foldAtomFuncType intAtomType intAtomType,
525+ atomFunc = (\((relIn):_) -> relationMin (castRelation relIn))},
503526 AtomFunction { atomFuncName = "lt",
504− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
527+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
505528 atomFunc = intAtomFuncLessThan False},
506529 AtomFunction { atomFuncName = "lte",
507− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
530+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
508531 atomFunc = intAtomFuncLessThan True},
509532 AtomFunction { atomFuncName = "gte",
510− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
533+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
511534 atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan False},
512535 AtomFunction { atomFuncName = "gt",
513− atomFuncType = [IntAtomType, IntAtomType, BoolAtomType],
536+ atomFuncType = [intAtomType, intAtomType, boolAtomType],
514537 atomFunc = boolAtomNot . (:[]) . intAtomFuncLessThan True},
515538 AtomFunction { atomFuncName = "not",
516− atomFuncType = [BoolAtomType, BoolAtomType],
539+ atomFuncType = [boolAtomType, boolAtomType],
517540 atomFunc = boolAtomNot}
518541 ]
519542
520543intAtomFuncLessThan :: Bool -> [Atom] -> Atom
521−intAtomFuncLessThan equality (iatom1:iatom2:_) = (\(IntAtom i1) (IntAtom i2) -> BoolAtom $ i1 `op` i2) iatom1 iatom2
544+intAtomFuncLessThan equality (iatom1:iatom2:_) = (\i1 i2 -> Atom $ ((unsafeCast i1)::Int) `op` unsafeCast i2) iatom1 iatom2
522545 where
523546 op = if equality then (<=) else (<)
524−intAtomFuncLessThan _ _= BoolAtom False
547+intAtomFuncLessThan _ _= Atom False
525548
526549boolAtomNot :: [Atom] -> Atom
527−boolAtomNot (BoolAtom bool:_) = BoolAtom $ not bool
528−boolAtomNot _ = BoolAtom False
550+boolAtomNot (bool:_) = Atom $ not (unsafeCast bool)
551+boolAtomNot _ = Atom False
529552