1{-# OPTIONS_GHC -fno-warn-orphans #-}
2module ProjectM36.DataTypes.Interval where
3import ProjectM36.AtomFunctionBody
5import ProjectM36.AtomType
6import ProjectM36.DataTypes.Primitive
7import ProjectM36.AtomFunctionError
8import qualified Data.HashSet as HS
10-- in lieu of typeclass support, we just hard-code the types which can be part of an interval
11supportsInterval :: AtomType -> Bool
12supportsInterval typ = case typ of
14 IntegerAtomType -> True
15 DoubleAtomType -> True
16 TextAtomType -> False -- just because it supports ordering, doesn't mean it makes sense in an interval
18 DateTimeAtomType -> True
19 ByteStringAtomType -> False
21 IntervalAtomType _ -> False
22 RelationAtomType _ -> False
23 ConstructedAtomType _ _ -> False --once we support an interval-style typeclass, we might enable this
24 TypeVariableType _ -> False
26supportsOrdering :: AtomType -> Bool
27supportsOrdering typ = case typ of
29 IntegerAtomType -> True
30 DoubleAtomType -> True
33 DateTimeAtomType -> True
34 ByteStringAtomType -> False
36 IntervalAtomType _ -> False
37 RelationAtomType _ -> False
38 ConstructedAtomType _ _ -> False --once we support an interval-style typeclass, we might enable this
39 TypeVariableType _ -> False
41atomCompare :: Atom -> Atom -> Either AtomFunctionError Ordering
42atomCompare a1 a2 = let aType = atomTypeForAtom a1
43 go a b = Right (compare a b)
44 typError = Left (AtomTypeDoesNotSupportOrderingError (prettyAtomType aType)) in
45 if atomTypeForAtom a1 /= atomTypeForAtom a2 then
46 Left AtomFunctionTypeMismatchError
47 else if not (supportsOrdering aType) then
51 (IntegerAtom a, IntegerAtom b) -> go a b
52 (IntAtom a, IntAtom b) -> go a b
53 (DoubleAtom a, DoubleAtom b) -> go a b
54 (TextAtom a, TextAtom b) -> go a b
55 (DayAtom a, DayAtom b) -> go a b
56 (DateTimeAtom a, DateTimeAtom b) -> go a b
59--check that interval is properly ordered and that the boundaries make sense
60createInterval :: Atom -> Atom -> OpenInterval -> OpenInterval -> Either AtomFunctionError Atom
61createInterval atom1 atom2 bopen eopen = do
62 cmp <- atomCompare atom1 atom2
64 GT -> Left InvalidIntervalOrderingError
65 EQ -> if bopen || eopen then
66 Left InvalidIntervalBoundariesError
70 where valid = IntervalAtom atom1 atom2 bopen eopen
72intervalAtomFunctions :: AtomFunctions
73intervalAtomFunctions = HS.fromList [
74 AtomFunction { atomFuncName = "interval",
75 atomFuncType = [TypeVariableType "a",
79 IntervalAtomType (TypeVariableType "a")],
80 atomFuncBody = compiledAtomFunctionBody $ \(atom1:atom2:BoolAtom bopen:BoolAtom eopen:_) -> do
81 let aType = atomTypeForAtom atom1
82 if supportsInterval aType then
83 createInterval atom1 atom2 bopen eopen
85 Left (AtomTypeDoesNotSupportIntervalError (prettyAtomType aType))
88 atomFuncName = "interval_overlaps",
89 atomFuncType = [IntervalAtomType (TypeVariableType "a"),
90 IntervalAtomType (TypeVariableType "a"),
92 atomFuncBody = compiledAtomFunctionBody $ \(i1@IntervalAtom{}:i2@IntervalAtom{}:_) -> do
93 res <- intervalOverlaps i1 i2
98intervalOverlaps :: Atom -> Atom -> Either AtomFunctionError Bool
99intervalOverlaps (IntervalAtom i1start i1end i1startopen i1endopen) (IntervalAtom i2start i2end i2startopen i2endopen) = do
100 cmp1 <- atomCompare i1start i2end
101 cmp2 <- atomCompare i2start i1end
102 let startcmp = if i1startopen || i2endopen then oplt else oplte
103 endcmp = if i2startopen || i1endopen then oplt else oplte
104 oplte op = op == LT || op == EQ
106 pure (startcmp cmp1 && endcmp cmp2)
107intervalOverlaps _ _ = Left AtomFunctionTypeMismatchError
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list