@@ -1,5 +1,6 @@
1{-# language AllowAmbiguousTypes #-}
1{-# language AllowAmbiguousTypes #-}
2{-# language DataKinds #-}
2{-# language DataKinds #-}
3+{-# language DefaultSignatures #-}
3{-# language DisambiguateRecordFields #-}
4{-# language DisambiguateRecordFields #-}
4{-# language FlexibleContexts #-}
5{-# language FlexibleContexts #-}
5{-# language FlexibleInstances #-}
6{-# language FlexibleInstances #-}
@@ -9,6 +10,7 @@
9{-# language StandaloneKindSignatures #-}
10{-# language StandaloneKindSignatures #-}
10{-# language TypeApplications #-}
11{-# language TypeApplications #-}
11{-# language TypeFamilies #-}
12{-# language TypeFamilies #-}
13+{-# language TypeOperators #-}
12{-# language UndecidableInstances #-}
14{-# language UndecidableInstances #-}
14module Rel8.Table.Serialize
16module Rel8.Table.Serialize
@@ -23,6 +25,11 @@ where
23import Data.Bifunctor ( bimap )
25import Data.Bifunctor ( bimap )
24import Data.Kind ( Constraint, Type )
26import Data.Kind ( Constraint, Type )
25import Data.List.NonEmpty ( NonEmpty )
27import Data.List.NonEmpty ( NonEmpty )
29+ ( Generic, Rep, from, to
30+ , (:*:)( (:*:) ), K1( K1 ), M1( M1 ), Meta( MetaSel ), D, C, S
32+import GHC.TypeLits ( KnownSymbol )
26import Prelude
33import Prelude
@@ -31,19 +38,17 @@ import qualified Hasql.Decoders as Hasql
32import Rel8.Expr ( Expr, Col(..) )
39import Rel8.Expr ( Expr, Col(..) )
33import Rel8.Expr.Serialize ( slitExpr, sparseValue )
40import Rel8.Expr.Serialize ( slitExpr, sparseValue )
41+import Rel8.Generic.Record ( Record(..) )
34import Rel8.Schema.Context ( Col(..) )
42import Rel8.Schema.Context ( Col(..) )
35import Rel8.Schema.Context.Label ( labeler, unlabeler )
43import Rel8.Schema.Context.Label ( labeler, unlabeler )
36import Rel8.Schema.HTable ( HTable, htabulate, htabulateA, hfield, hspecs )
44import Rel8.Schema.HTable ( HTable, htabulate, htabulateA, hfield, hspecs )
37−import Rel8.Schema.HTable.Label ( hlabel, hunlabel )
45+import Rel8.Schema.HTable.Label ( HLabel, hlabel, hunlabel )
38−import Rel8.Schema.HTable.Quartet ( HQuartet(..) )
46+import Rel8.Schema.HTable.Product ( HProduct(..) )
39−import Rel8.Schema.HTable.Quintet ( HQuintet(..) )
40−import Rel8.Schema.HTable.Pair ( HPair(..) )
41−import Rel8.Schema.HTable.Trio ( HTrio(..) )
42import Rel8.Schema.HTable.Type ( HType(..) )
47import Rel8.Schema.HTable.Type ( HType(..) )
43import Rel8.Schema.Null ( NotNull, Sql )
48import Rel8.Schema.Null ( NotNull, Sql )
44import Rel8.Schema.Result ( Result )
49import Rel8.Schema.Result ( Result )
45import Rel8.Schema.Spec ( SSpec(..), KnownSpec )
50import Rel8.Schema.Spec ( SSpec(..), KnownSpec )
46−import Rel8.Table ( Table, Columns, fromColumns, toColumns )
51+import Rel8.Table ( Table, Columns, fromColumns, toColumns, GColumns )
47import Rel8.Table.Either ( EitherTable )
52import Rel8.Table.Either ( EitherTable )
48import Rel8.Table.List ( ListTable )
53import Rel8.Table.List ( ListTable )
49import Rel8.Table.Maybe ( MaybeTable )
54import Rel8.Table.Maybe ( MaybeTable )
@@ -64,6 +69,59 @@ class Table Expr exprs => ToExprs exprs a where
64 fromResult :: Columns exprs (Col Result) -> a
69 fromResult :: Columns exprs (Col Result) -> a
65 toResult :: a -> Columns exprs (Col Result)
70 toResult :: a -> Columns exprs (Col Result)
72+ default fromResult ::
74+ , GToExprs (Rep (Record exprs)) (Rep (Record a))
75+ , Columns exprs ~ GColumns (Rep (Record exprs))
77+ => Columns exprs (Col Result) -> a
78+ fromResult = unrecord . to . gfromResult @(Rep (Record exprs))
82+ , GToExprs (Rep (Record exprs)) (Rep (Record a))
83+ , Columns exprs ~ GColumns (Rep (Record exprs))
85+ => a -> Columns exprs (Col Result)
86+ toResult = gtoResult @(Rep (Record exprs)) . from . Record
89+type GToExprs :: (Type -> Type) -> (Type -> Type) -> Constraint
90+class GToExprs exprs rep where
91+ gfromResult :: GColumns exprs (Col Result) -> rep x
92+ gtoResult :: rep x -> GColumns exprs (Col Result)
95+instance GToExprs exprs rep => GToExprs (M1 D c exprs) (M1 D c rep) where
96+ gfromResult = M1 . gfromResult @exprs
97+ gtoResult (M1 a) = gtoResult @exprs a
100+instance GToExprs exprs rep => GToExprs (M1 C c exprs) (M1 C c rep) where
101+ gfromResult = M1 . gfromResult @exprs
102+ gtoResult (M1 a) = gtoResult @exprs a
105+instance (GToExprs exprs1 rep1, GToExprs exprs2 rep2) =>
106+ GToExprs (exprs1 :*: exprs2) (rep1 :*: rep2)
108+ gfromResult (HProduct a b) = gfromResult @exprs1 a :*: gfromResult @exprs2 b
109+ gtoResult (a :*: b) = HProduct (gtoResult @exprs1 a) (gtoResult @exprs2 b)
115+ , GColumns (M1 S meta k1) ~ HLabel label (Columns exprs)
116+ , meta ~ 'MetaSel ('Just label) _su _ss _ds
120+ => GToExprs (M1 S meta k1) (M1 S meta k1')
122+ gfromResult = M1 . K1 . fromResult @exprs . hunlabel unlabeler
123+ gtoResult (M1 (K1 a)) = hlabel labeler (toResult @exprs a)
68instance {-# OVERLAPPABLE #-} (Sql DBType a, x ~ Expr a) => ToExprs x a where
126instance {-# OVERLAPPABLE #-} (Sql DBType a, x ~ Expr a) => ToExprs x a where
69 fromResult (HType (Result a)) = a
127 fromResult (HType (Result a)) = a
@@ -127,15 +185,6 @@ instance (ToExprs exprs1 a, ToExprs exprs2 b, x ~ TheseTable exprs1 exprs2) =>
128instance (ToExprs exprs1 a, ToExprs exprs2 b, x ~ (exprs1, exprs2)) =>
186instance (ToExprs exprs1 a, ToExprs exprs2 b, x ~ (exprs1, exprs2)) =>
129 ToExprs x (a, b)
187 ToExprs x (a, b)
131− fromResult (HPair a b) =
132− ( fromResult @exprs1 $ hunlabel unlabeler a
133− , fromResult @exprs2 $ hunlabel unlabeler b
135− toResult (a, b) = HPair
136− { hfst = hlabel labeler $ toResult @exprs1 a
137− , hsnd = hlabel labeler $ toResult @exprs2 b
@@ -143,18 +192,8 @@ instance
143 , ToExprs exprs2 b
192 , ToExprs exprs2 b
144 , ToExprs exprs3 c
193 , ToExprs exprs3 c
145 , x ~ (exprs1, exprs2, exprs3)
194 , x ~ (exprs1, exprs2, exprs3)
146− ) => ToExprs x (a, b, c)
196+ => ToExprs x (a, b, c)
148− fromResult (HTrio a b c) =
149− ( fromResult @exprs1 $ hunlabel unlabeler a
150− , fromResult @exprs2 $ hunlabel unlabeler b
151− , fromResult @exprs3 $ hunlabel unlabeler c
153− toResult (a, b, c) = HTrio
154− { hfst = hlabel labeler $ toResult @exprs1 a
155− , hsnd = hlabel labeler $ toResult @exprs2 b
156− , htrd = hlabel labeler $ toResult @exprs3 c
@@ -163,20 +202,8 @@ instance
163 , ToExprs exprs3 c
202 , ToExprs exprs3 c
164 , ToExprs exprs4 d
203 , ToExprs exprs4 d
165 , x ~ (exprs1, exprs2, exprs3, exprs4)
204 , x ~ (exprs1, exprs2, exprs3, exprs4)
166− ) => ToExprs x (a, b, c, d)
206+ => ToExprs x (a, b, c, d)
168− fromResult (HQuartet a b c d) =
169− ( fromResult @exprs1 $ hunlabel unlabeler a
170− , fromResult @exprs2 $ hunlabel unlabeler b
171− , fromResult @exprs3 $ hunlabel unlabeler c
172− , fromResult @exprs4 $ hunlabel unlabeler d
174− toResult (a, b, c, d) = HQuartet
175− { hfst = hlabel labeler $ toResult @exprs1 a
176− , hsnd = hlabel labeler $ toResult @exprs2 b
177− , htrd = hlabel labeler $ toResult @exprs3 c
178− , hfrt = hlabel labeler $ toResult @exprs4 d
@@ -186,22 +213,8 @@ instance
186 , ToExprs exprs4 d
213 , ToExprs exprs4 d
187 , ToExprs exprs5 e
214 , ToExprs exprs5 e
188 , x ~ (exprs1, exprs2, exprs3, exprs4, exprs5)
215 , x ~ (exprs1, exprs2, exprs3, exprs4, exprs5)
189− ) => ToExprs x (a, b, c, d, e)
217+ => ToExprs x (a, b, c, d, e)
191− fromResult (HQuintet a b c d e) =
192− ( fromResult @exprs1 $ hunlabel unlabeler a
193− , fromResult @exprs2 $ hunlabel unlabeler b
194− , fromResult @exprs3 $ hunlabel unlabeler c
195− , fromResult @exprs4 $ hunlabel unlabeler d
196− , fromResult @exprs5 $ hunlabel unlabeler e
198− toResult (a, b, c, d, e) = HQuintet
199− { hfst = hlabel labeler $ toResult @exprs1 a
200− , hsnd = hlabel labeler $ toResult @exprs2 b
201− , htrd = hlabel labeler $ toResult @exprs3 c
202− , hfrt = hlabel labeler $ toResult @exprs4 d
203− , hfft = hlabel labeler $ toResult @exprs5 e
207instance (HTable t, result ~ Col Result, x ~ t (Col Expr)) =>
220instance (HTable t, result ~ Col Result, x ~ t (Col Expr)) =>