@@ -1,17 +1,18 @@
1{-# LANGUAGE FlexibleInstances, FlexibleContexts, TypeOperators, UndecidableInstances, ScopedTypeVariables, DefaultSignatures #-}
1{-# LANGUAGE FlexibleInstances, FlexibleContexts, TypeOperators, UndecidableInstances, ScopedTypeVariables, DefaultSignatures #-}
2+{-# LANGUAGE DeriveGeneric #-}
2module ProjectM36.Tupleable where
3module ProjectM36.Tupleable where
3import ProjectM36.Base
4import ProjectM36.Base
4import ProjectM36.Error
5import ProjectM36.Error
5import ProjectM36.Tuple
6import ProjectM36.Tuple
6import ProjectM36.TupleSet
7import ProjectM36.TupleSet
7import ProjectM36.Atomable
8import ProjectM36.Atomable
9+import ProjectM36.DataTypes.Primitive
8import ProjectM36.Attribute hiding (null)
10import ProjectM36.Attribute hiding (null)
9import GHC.Generics
11import GHC.Generics
10import qualified Data.Vector as V
12import qualified Data.Vector as V
11import qualified Data.Text as T
13import qualified Data.Text as T
12import Data.Monoid
14import Data.Monoid
13import Data.Foldable
15import Data.Foldable
17data Test1T = Test1C {
18data Test1T = Test1C {
@@ -46,15 +47,15 @@ toInsertExpr vals rvName = do
46class Tupleable a where
47class Tupleable a where
47 toTuple :: a -> RelationTuple
48 toTuple :: a -> RelationTuple
49− fromTuple :: RelationTuple -> a
50+ fromTuple :: RelationTuple -> Either RelationalError a
51 toAttributes :: a -> Attributes
52 toAttributes :: a -> Attributes
53 default toTuple :: (Generic a, TupleableG (Rep a)) => a -> RelationTuple
54 default toTuple :: (Generic a, TupleableG (Rep a)) => a -> RelationTuple
54 toTuple v = toTupleG (from v)
55 toTuple v = toTupleG (from v)
56− default fromTuple :: (Generic a, TupleableG (Rep a)) => RelationTuple -> a
57+ default fromTuple :: (Generic a, TupleableG (Rep a)) => RelationTuple -> Either RelationalError a
57− fromTuple tup = to (fromTupleG tup)
58+ fromTuple tup = to <$> fromTupleG tup
59 default toAttributes :: (Generic a, TupleableG (Rep a)) => a -> Attributes
60 default toAttributes :: (Generic a, TupleableG (Rep a)) => a -> Attributes
60 toAttributes v = toAttributesG (from v)
61 toAttributes v = toAttributesG (from v)
@@ -62,13 +63,13 @@ class Tupleable a where
62class TupleableG g where
63class TupleableG g where
63 toTupleG :: g a -> RelationTuple
64 toTupleG :: g a -> RelationTuple
64 toAttributesG :: g a -> Attributes
65 toAttributesG :: g a -> Attributes
65− fromTupleG :: RelationTuple -> g a
66+ fromTupleG :: RelationTuple -> Either RelationalError (g a)
67--data type metadata
68--data type metadata
68instance (Datatype c, TupleableG a) => TupleableG (M1 D c a) where
69instance (Datatype c, TupleableG a) => TupleableG (M1 D c a) where
69 toTupleG (M1 v) = toTupleG v
70 toTupleG (M1 v) = toTupleG v
70 toAttributesG (M1 v) = toAttributesG v
71 toAttributesG (M1 v) = toAttributesG v
71− fromTupleG v = M1 (fromTupleG v)
72+ fromTupleG v = M1 <$> fromTupleG v
73--constructor metadata
74--constructor metadata
74instance (Constructor c, TupleableG a, AtomableG a) => TupleableG (M1 C c a) where
75instance (Constructor c, TupleableG a, AtomableG a) => TupleableG (M1 C c a) where
@@ -82,13 +83,13 @@ instance (Constructor c, TupleableG a, AtomableG a) => TupleableG (M1 C c a) whe
82 attr) counter attrsToCheck
83 attr) counter attrsToCheck
83 atoms = V.fromList (toAtomsG v)
84 atoms = V.fromList (toAtomsG v)
84 toAttributesG (M1 v) = toAttributesG v
85 toAttributesG (M1 v) = toAttributesG v
85− fromTupleG tup = M1 (fromTupleG tup)
86+ fromTupleG tup = M1 <$> fromTupleG tup
87-- product types
88-- product types
88instance (TupleableG a, TupleableG b) => TupleableG (a :*: b) where
89instance (TupleableG a, TupleableG b) => TupleableG (a :*: b) where
89 toTupleG = error "toTupleG"
90 toTupleG = error "toTupleG"
90 toAttributesG ~(x :*: y) = toAttributesG x V.++ toAttributesG y --a bit of extra laziness prevents whnf so that we can use toAttributes (undefined :: Test2T Int Int) without throwing an exception
91 toAttributesG ~(x :*: y) = toAttributesG x V.++ toAttributesG y --a bit of extra laziness prevents whnf so that we can use toAttributes (undefined :: Test2T Int Int) without throwing an exception
91− fromTupleG tup = fromTupleG tup :*: fromTupleG (trimTuple 1 tup)
92+ fromTupleG tup = (:*:) <$> fromTupleG tup <*> fromTupleG (trimTuple 1 tup)
93--selector/record
94--selector/record
94instance (Selector c, AtomableG a) => TupleableG (M1 S c a) where
95instance (Selector c, AtomableG a) => TupleableG (M1 S c a) where
@@ -98,13 +99,17 @@ instance (Selector c, AtomableG a) => TupleableG (M1 S c a) where
98 name = T.pack (selName m)
99 name = T.pack (selName m)
99 aType = toAtomTypeG v
100 aType = toAtomTypeG v
100 fromTupleG tup = if null name then -- non-record type, just pull off the first tuple item
101 fromTupleG tup = if null name then -- non-record type, just pull off the first tuple item
101− M1 (atomv (V.head (tupleAtoms tup)))
102+ M1 <$> atomv (V.head (tupleAtoms tup))
103− case atomForAttributeName (T.pack name) tup of
104+ atom <- atomForAttributeName (T.pack name) tup
104− Left _ -> error ("no such record name: " ++ name)
105+ val <- atomv atom
105− Right atom -> M1 (atomv atom)
106+ pure (M1 val)
108+ expectedAtomType = atomType (V.head (toAttributesG (undefined :: M1 S c a x)))
109+ atomv atom = maybe (Left (AtomTypeMismatchError
111+ (atomTypeForAtom atom)
107− atomv atom = fromMaybe (error "no such atom conversion") (fromAtomG atom [atom])
112+ )) Right (fromAtomG atom [atom])
108 name = selName (undefined :: M1 S c a x)
113 name = selName (undefined :: M1 S c a x)
110--constructors with no arguments
115--constructors with no arguments
@@ -112,6 +117,6 @@ instance (Selector c, AtomableG a) => TupleableG (M1 S c a) where
112instance TupleableG U1 where
117instance TupleableG U1 where
113 toTupleG _= emptyTuple
118 toTupleG _= emptyTuple
114 toAttributesG _ = emptyAttributes
119 toAttributesG _ = emptyAttributes
115− fromTupleG _ = U1
120+ fromTupleG _ = pure U1