module Sqel.Sum where
import Generics.SOP (NP ((:*)))
import Generics.SOP.GGP (GCode, GDatatypeInfoOf)
import Generics.SOP.Type.Metadata (ConstructorInfo (Constructor, Infix, Record), DatatypeInfo (ADT))
import Prelude hiding (sum)
import Sqel.Comp (CompColumn (compColumn), CompName (compName), ConstructorFields, MetaFor, RecordFields)
import Sqel.Data.Dd (
Comp (Prod, Sum),
CompInc (Merge, Nest),
ConCol,
Dd (Dd),
DdInc (DdMerge, DdNest),
DdK (DdK),
DdSort (DdCon, DdSum),
DdStruct (DdComp, DdPrim),
DdType,
ProdType (Con),
ProductField (ProductField),
Struct (Comp, Prim),
)
import Sqel.Data.Mods (pattern NoMods, NoMods)
import Sqel.Data.Sel (
IndexName,
MkTSel (mkTSel),
Sel (SelAuto, SelIndex),
SelPrefix (DefaultPrefix, SelPrefix),
SelW (SelWAuto, SelWIndex),
TSel (TSel),
TypeName,
)
import Sqel.Merge (merge)
import Sqel.Names.Rename (Rename (rename))
import Sqel.Names.Set (SetName)
import Sqel.Prim (IndexColumn, IndexColumnWith, primIndex)
import qualified Sqel.Type as T
import Type.Errors (ErrorMessage (Text))
type family SumFields' (fields :: [ConstructorInfo]) (ass :: [[Type]]) :: [ProductField] where
SumFields' '[] '[] = '[]
SumFields' ('Record name fields : cons) (as : ass) = 'ProductField name (ConCol name 'True (RecordFields fields as) as) : SumFields' cons ass
SumFields' ('Constructor name : cons) (as : ass) = 'ProductField name (ConCol name 'False (ConstructorFields name 0 as) as) : SumFields' cons ass
SumFields' ('Infix conName _ _ : _) _ =
TypeError ("Infix constructor not supported: " <> conName)
type family SumFields (info :: DatatypeInfo) (ass :: [[Type]]) :: [ProductField] where
SumFields ('ADT _ _ cons _) ass = SumFields' cons ass
SumFields info _ =
TypeError ("SumFields:" % info)
class DdType s ~ a => SumWith a isel imods arg s | a isel imods arg -> s where
sumWith :: Dd ('DdK isel imods Int64 'Prim) -> arg -> Dd s
instance (
b ~ a,
CompName a ('TSel prefix name),
fields ~ SumFields (GDatatypeInfoOf a) (GCode a),
meta ~ MetaFor "sum type" ('ShowType a) "sum",
CompColumn meta fields a arg s
) => SumWith b isel imods arg ('DdK 'SelAuto NoMods a ('Comp ('TSel prefix name) 'Sum 'Nest ('DdK isel imods Int64 'Prim : s))) where
sumWith :: Dd ('DdK isel imods Int64 'Prim)
-> arg
-> Dd
('DdK
'SelAuto
NoMods
a
('Comp
('TSel prefix name) 'Sum 'Nest ('DdK isel imods Int64 'Prim : s)))
sumWith Dd ('DdK isel imods Int64 'Prim)
index arg
arg =
forall (sel :: Sel) (mods :: [*]) (s1 :: Struct) a.
SelW sel -> Mods mods -> DdStruct s1 -> Dd ('DdK sel mods a s1)
Dd SelW 'SelAuto
SelWAuto forall (ps :: [*]). (ps ~ NoMods) => Mods ps
NoMods (forall (sel :: TSel) (c :: Comp) (i :: CompInc) (sub :: [DdK]).
TSelW sel
-> DdSort c -> DdInc i -> NP Dd sub -> DdStruct ('Comp sel c i sub)
DdComp (forall a (sel :: TSel). CompName a sel => TSelW sel
compName @a) DdSort 'Sum
DdSum DdInc 'Nest
DdNest (Dd ('DdK isel imods Int64 'Prim)
index forall {k} (a :: k -> *) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* forall (meta :: CompMeta) (fields :: [ProductField]) a arg
(s :: [DdK]).
CompColumn meta fields a arg s =>
arg -> NP Dd s
compColumn @meta @fields @a arg
arg))
class DdType s ~ a => Sum a arg s | a arg -> s where
sum :: arg -> Dd s
instance (
b ~ a,
CompName a ('TSel prefix name),
IndexName 'DefaultPrefix name iname,
fields ~ SumFields (GDatatypeInfoOf a) (GCode a),
meta ~ MetaFor "sum type" ('ShowType a) "sum",
CompColumn meta fields a arg s
) => Sum b arg ('DdK 'SelAuto NoMods a ('Comp ('TSel prefix name) 'Sum 'Nest (IndexColumn name : s))) where
sum :: arg
-> Dd
('DdK
'SelAuto
NoMods
a
('Comp ('TSel prefix name) 'Sum 'Nest (IndexColumn name : s)))
sum =
forall a (isel :: Sel) (imods :: [*]) arg (s :: DdK).
SumWith a isel imods arg s =>
Dd ('DdK isel imods Int64 'Prim) -> arg -> Dd s
sumWith forall (tpe :: Symbol) (name :: Symbol).
IndexName 'DefaultPrefix tpe name =>
Dd (IndexColumn tpe)
primIndex
sumAs ::
∀ (name :: Symbol) (a :: Type) (s :: DdK) (arg :: Type) .
Sum a arg s =>
Rename s (SetName s name) =>
arg ->
Dd (SetName s name)
sumAs :: forall (name :: Symbol) a (s :: DdK) arg.
(Sum a arg s, Rename s (SetName s name)) =>
arg -> Dd (SetName s name)
sumAs =
forall (s0 :: DdK) (s1 :: DdK). Rename s0 s1 => Dd s0 -> Dd s1
rename forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a arg (s :: DdK). Sum a arg s => arg -> Dd s
sum @a @_ @s
mergeSum ::
∀ (a :: Type) (s :: DdK) (arg :: Type) .
Sum a arg s =>
arg ->
Dd (T.Merge s)
mergeSum :: forall a (s :: DdK) arg. Sum a arg s => arg -> Dd (Merge s)
mergeSum =
forall (s :: DdK). Dd s -> Dd (Merge s)
merge forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a arg (s :: DdK). Sum a arg s => arg -> Dd s
sum @a @_ @s
class DdType s ~ a => ConColumn a arg s | a arg -> s where
con :: arg -> Dd s
instance (
a ~ ConCol name record fields as,
MkTSel ('TSel 'DefaultPrefix name),
meta ~ MetaFor "constructor" ('Text name) "con",
CompColumn meta fields a arg s
) => ConColumn a arg ('DdK 'SelAuto NoMods (ConCol name record fields as) ('Comp ('TSel 'DefaultPrefix name) ('Prod ('Con as)) 'Nest s)) where
con :: arg
-> Dd
('DdK
'SelAuto
NoMods
(ConCol name record fields as)
('Comp ('TSel 'DefaultPrefix name) ('Prod ('Con as)) 'Nest s))
con arg
arg =
forall (sel :: Sel) (mods :: [*]) (s1 :: Struct) a.
SelW sel -> Mods mods -> DdStruct s1 -> Dd ('DdK sel mods a s1)
Dd SelW 'SelAuto
SelWAuto forall (ps :: [*]). (ps ~ NoMods) => Mods ps
NoMods (forall (sel :: TSel) (c :: Comp) (i :: CompInc) (sub :: [DdK]).
TSelW sel
-> DdSort c -> DdInc i -> NP Dd sub -> DdStruct ('Comp sel c i sub)
DdComp forall (sel :: TSel). MkTSel sel => TSelW sel
mkTSel forall (as :: [*]). DdSort ('Prod ('Con as))
DdCon DdInc 'Nest
DdNest (forall (meta :: CompMeta) (fields :: [ProductField]) a arg
(s :: [DdK]).
CompColumn meta fields a arg s =>
arg -> NP Dd s
compColumn @meta @fields @(ConCol name record fields as) arg
arg))
conAs ::
∀ (name :: Symbol) (a :: Type) (s :: DdK) (arg :: Type) .
ConColumn a arg s =>
Rename s (SetName s name) =>
arg ->
Dd (SetName s name)
conAs :: forall (name :: Symbol) a (s :: DdK) arg.
(ConColumn a arg s, Rename s (SetName s name)) =>
arg -> Dd (SetName s name)
conAs =
forall (s0 :: DdK) (s1 :: DdK). Rename s0 s1 => Dd s0 -> Dd s1
rename forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a arg (s :: DdK). ConColumn a arg s => arg -> Dd s
con @a @_ @s
type family Con1Fields (con :: Type) :: [ProductField] where
Con1Fields (ConCol _ 'True '[f] _) = '[f]
Con1Fields (ConCol name 'False '[ 'ProductField _ a] _) = '[ 'ProductField name a]
class DdType s ~ a => Con1Column a arg s | a arg -> s where
con1 :: arg -> Dd s
instance (
a ~ ConCol name record fields as,
TypeName 'DefaultPrefix name tname,
meta ~ MetaFor "constructor" ('Text name) "con1",
CompColumn meta (Con1Fields a) a arg s
) => Con1Column a arg ('DdK 'SelAuto NoMods (ConCol name record fields as) ('Comp ('TSel 'DefaultPrefix name) ('Prod ('Con as)) 'Merge s)) where
con1 :: arg
-> Dd
('DdK
'SelAuto
NoMods
(ConCol name record fields as)
('Comp ('TSel 'DefaultPrefix name) ('Prod ('Con as)) 'Merge s))
con1 arg
arg =
forall (sel :: Sel) (mods :: [*]) (s1 :: Struct) a.
SelW sel -> Mods mods -> DdStruct s1 -> Dd ('DdK sel mods a s1)
Dd SelW 'SelAuto
SelWAuto forall (ps :: [*]). (ps ~ NoMods) => Mods ps
NoMods (forall (sel :: TSel) (c :: Comp) (i :: CompInc) (sub :: [DdK]).
TSelW sel
-> DdSort c -> DdInc i -> NP Dd sub -> DdStruct ('Comp sel c i sub)
DdComp forall (sel :: TSel). MkTSel sel => TSelW sel
mkTSel forall (as :: [*]). DdSort ('Prod ('Con as))
DdCon DdInc 'Merge
DdMerge (forall (meta :: CompMeta) (fields :: [ProductField]) a arg
(s :: [DdK]).
CompColumn meta fields a arg s =>
arg -> NP Dd s
compColumn @meta @(Con1Fields a) @(ConCol name record fields as) arg
arg))
type family RenameCon1 (name :: Symbol) (a :: Type) :: Type where
RenameCon1 name (ConCol _ record '[ 'ProductField _ a] as) =
ConCol name record '[ 'ProductField name a] as
RenameCon1 _ a =
TypeError ("RenameCon1:" % a)
class DdType s ~ a => Con1AsColumn name a arg s | name a arg -> s where
con1As :: arg -> Dd s
instance (
a ~ ConCol _name record _fields as,
TypeName 'DefaultPrefix name tname,
fields ~ Con1Fields (RenameCon1 name a),
meta ~ MetaFor "constructor" ('Text name) "con1As",
CompColumn meta fields a arg s
) => Con1AsColumn name a arg ('DdK 'SelAuto NoMods a ('Comp ('TSel 'DefaultPrefix name) ('Prod ('Con as)) 'Merge s)) where
con1As :: arg
-> Dd
('DdK
'SelAuto
NoMods
a
('Comp ('TSel 'DefaultPrefix name) ('Prod ('Con as)) 'Merge s))
con1As arg
arg =
forall (sel :: Sel) (mods :: [*]) (s1 :: Struct) a.
SelW sel -> Mods mods -> DdStruct s1 -> Dd ('DdK sel mods a s1)
Dd SelW 'SelAuto
SelWAuto forall (ps :: [*]). (ps ~ NoMods) => Mods ps
NoMods (forall (sel :: TSel) (c :: Comp) (i :: CompInc) (sub :: [DdK]).
TSelW sel
-> DdSort c -> DdInc i -> NP Dd sub -> DdStruct ('Comp sel c i sub)
DdComp forall (sel :: TSel). MkTSel sel => TSelW sel
mkTSel forall (as :: [*]). DdSort ('Prod ('Con as))
DdCon DdInc 'Merge
DdMerge (forall (meta :: CompMeta) (fields :: [ProductField]) a arg
(s :: [DdK]).
CompColumn meta fields a arg s =>
arg -> NP Dd s
compColumn @meta @fields @a arg
arg))
type SetIndexPrefix :: Symbol -> DdK -> DdK -> Constraint
class SetIndexPrefix prefix s0 s1 | prefix s0 -> s1 where
setIndexPrefix :: Dd s0 -> Dd s1
instance (
IndexName ('SelPrefix prefix) tpe iname
) => SetIndexPrefix prefix ('DdK sel mods a ('Comp tsel 'Sum i ('DdK ('SelIndex oldPrefix tpe) NoMods Int64 'Prim : cons))) ('DdK sel mods a ('Comp tsel 'Sum i (IndexColumnWith ('SelPrefix prefix) tpe : cons))) where
setIndexPrefix :: Dd
('DdK
sel
mods
a
('Comp
tsel
'Sum
i
('DdK ('SelIndex oldPrefix tpe) NoMods Int64 'Prim : cons)))
-> Dd
('DdK
sel
mods
a
('Comp
tsel 'Sum i (IndexColumnWith ('SelPrefix prefix) tpe : cons)))
setIndexPrefix (Dd SelW sel
sel Mods mods
mods (DdComp TSelW sel
tsel DdSort c
DdSum DdInc i
i (Dd (SelWIndex Proxy name
Proxy) Mods mods
NoMods DdStruct s1
DdPrim :* NP Dd xs
cons))) =
forall (sel :: Sel) (mods :: [*]) (s1 :: Struct) a.
SelW sel -> Mods mods -> DdStruct s1 -> Dd ('DdK sel mods a s1)
Dd SelW sel
sel Mods mods
mods (forall (sel :: TSel) (c :: Comp) (i :: CompInc) (sub :: [DdK]).
TSelW sel
-> DdSort c -> DdInc i -> NP Dd sub -> DdStruct ('Comp sel c i sub)
DdComp TSelW sel
tsel DdSort 'Sum
DdSum DdInc i
i (forall (sel :: Sel) (mods :: [*]) (s1 :: Struct) a.
SelW sel -> Mods mods -> DdStruct s1 -> Dd ('DdK sel mods a s1)
Dd (forall (prefix :: SelPrefix) (tpe :: Symbol) (name :: Symbol).
IndexName prefix tpe name =>
Proxy name -> SelW ('SelIndex prefix tpe)
SelWIndex forall {k} (t :: k). Proxy t
Proxy) forall (ps :: [*]). (ps ~ NoMods) => Mods ps
NoMods DdStruct 'Prim
DdPrim forall {k} (a :: k -> *) (x :: k) (xs :: [k]).
a x -> NP a xs -> NP a (x : xs)
:* NP Dd xs
cons))
setIndexPrefix Dd
('DdK
sel
mods
a
('Comp
tsel
'Sum
i
('DdK ('SelIndex oldPrefix tpe) NoMods Int64 'Prim : cons)))
_ =
forall a. HasCallStack => [Char] -> a
error [Char]
"ghc bug?"
indexPrefix ::
∀ prefix s0 s1 .
SetIndexPrefix prefix s0 s1 =>
Dd s0 ->
Dd s1
indexPrefix :: forall (prefix :: Symbol) (s0 :: DdK) (s1 :: DdK).
SetIndexPrefix prefix s0 s1 =>
Dd s0 -> Dd s1
indexPrefix =
forall (prefix :: Symbol) (s0 :: DdK) (s1 :: DdK).
SetIndexPrefix prefix s0 s1 =>
Dd s0 -> Dd s1
setIndexPrefix @prefix