on master help sign in
oops- fix critical bug in Atomable list instance
463bb37AgentM
docs/new_datatypes.markdown+1−1
@@ -104,6 +104,6 @@ The essential ```Atomable``` typeclass functions are:
104| ```toAtomType :: a -> AtomType``` | generate a database AtomType for a Haskell datatype |
104| ```toAtomType :: a -> AtomType``` | generate a database AtomType for a Haskell datatype |
105| ```toDatabaseContextExpr :: a -> DatabaseContextExpr``` | generate a ```DatabaseContextExpr``` which can be executed against a database context in order to add the new type |
105| ```toDatabaseContextExpr :: a -> DatabaseContextExpr``` | generate a ```DatabaseContextExpr``` which can be executed against a database context in order to add the new type |
106
106
107−In addition, basic Haskell data types like ```Int```, ```Double```, ```Text```, ```Day```, ```Bool```, ```UTCTime```, ```ByteString```, and more already have Atomable instances ready-to-go. In addition, an ```Atomable``` instance is available for lists: ```Atomable a => [a]```, though one should be very careful not to use this in a common anti-pattern. Typically, it makes more sense to store one-to-many relationships as discrete relation variables; when storing them as lists, one gives up the various query capabilities and optimizations of the relational algebra.
107+In addition, basic Haskell data types like ```Int```, ```Double```, ```Text```, ```Day```, ```Bool```, ```UTCTime```, and ```ByteString``` already have Atomable instances ready-to-go. In addition, an ```Atomable``` instance is available for lists: ```Atomable a => [a]```, though one should be very careful not to use this in a common anti-pattern. Typically, it makes more sense to store one-to-many relationships as discrete relation variables; when storing them as lists, one gives up the various query capabilities and optimizations of the relational algebra.
108
108
109To be clear, these data types are not black boxes once stored in the database. These new types can be scanned and manipulated by Haskell scripts which can be created at runtime. For more information, read about [```AtomFunction```s](/docs/atomfunctions.markdown).
109To be clear, these data types are not black boxes once stored in the database. These new types can be scanned and manipulated by Haskell scripts which can be created at runtime. For more information, read about [```AtomFunction```s](/docs/atomfunctions.markdown).
src/lib/ProjectM36/Atomable.hs+1−1
@@ -112,7 +112,7 @@ instance Atomable Relation where
112--convert to ADT list
112--convert to ADT list
113instance Atomable a => Atomable [a] where
113instance Atomable a => Atomable [a] where
114 toAtom [] = ConstructedAtom "Empty" (listAtomType (toAtomType (undefined :: a))) []
114 toAtom [] = ConstructedAtom "Empty" (listAtomType (toAtomType (undefined :: a))) []
115− toAtom (x:xs) = ConstructedAtom "Cons" (listAtomType (toAtomType x)) (map toAtom xs)
115+ toAtom (x:xs) = ConstructedAtom "Cons" (listAtomType (toAtomType x)) (map toAtom (x:xs))
116
116
117 fromAtom (ConstructedAtom "Empty" _ _) = []
117 fromAtom (ConstructedAtom "Empty" _ _) = []
118 fromAtom (ConstructedAtom "Cons" _ (x:xs)) = fromAtom x:map fromAtom xs
118 fromAtom (ConstructedAtom "Cons" _ (x:xs)) = fromAtom x:map fromAtom xs
test/Relation/Atomable.hs+10−1
@@ -26,6 +26,9 @@ data Test4T = Test4Ca Int |
26 Test4Cb Int
26 Test4Cb Int
27 deriving (Show, Generic, Eq, Binary, NFData, Atomable)
27 deriving (Show, Generic, Eq, Binary, NFData, Atomable)
28
28
29+data TestListT = TestListC [Int]
30+ deriving (Show, Generic, Eq, Binary, NFData, Atomable)
31+
29data Test5T = Test5C {
32data Test5T = Test5C {
30 con1 :: Int,
33 con1 :: Int,
31 con2 :: Int
34 con2 :: Int
@@ -37,7 +40,7 @@ main = do
37 if errors tcounts + failures tcounts > 0 then exitFailure else exitSuccess
40 if errors tcounts + failures tcounts > 0 then exitFailure else exitSuccess
38
41
39testList :: Test
42testList :: Test
40−testList = TestList [testHaskell2DB, testADT1, testADT2, testADT3, testADT4, testADT5, testBasicMarshaling]
43+testList = TestList [testHaskell2DB, testADT1, testADT2, testADT3, testADT4, testADT5, testBasicMarshaling, testListInstance]
41
44
42-- test some basic data types like int, day, etc.
45-- test some basic data types like int, day, etc.
43testBasicMarshaling :: Test
46testBasicMarshaling :: Test
@@ -106,3 +109,9 @@ testADT5 = TestCase $ do
106
109
107checkExecuteDatabaseContextExpr :: SessionId -> Connection -> DatabaseContextExpr -> IO ()
110checkExecuteDatabaseContextExpr :: SessionId -> Connection -> DatabaseContextExpr -> IO ()
108checkExecuteDatabaseContextExpr sessionId dbconn expr = executeDatabaseContextExpr sessionId dbconn expr >>= maybe (pure ()) (\err -> assertFailure (show err))
111checkExecuteDatabaseContextExpr sessionId dbconn expr = executeDatabaseContextExpr sessionId dbconn expr >>= maybe (pure ()) (\err -> assertFailure (show err))
112+
113+testListInstance :: Test
114+testListInstance = TestCase $ do
115+ let example = TestListC [3,4,5]
116+ traceShowM (toAtom example)
117+ assertEqual "List instance" example (fromAtom (toAtom example))