-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathDSL.hs
More file actions
85 lines (67 loc) · 3.08 KB
/
DSL.hs
File metadata and controls
85 lines (67 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
{-# LANGUAGE AllowAmbiguousTypes #-}
module Data.Schematic.DSL where
import Data.Kind
import Data.Schematic.Compat
import Data.Schematic.Lens
import Data.Schematic.Schema
import Data.Scientific
import Data.Singletons
import Data.Singletons.Prelude hiding ((:.))
import Data.Singletons.TypeLits
import Data.Tagged
import Data.Text as T
import Data.Union
import qualified Data.Vector as V
import Data.Vinyl
import Data.Vinyl.Functor
type Constructor a
= forall fields b
. (fields ~ FieldsOf a, FSubset fields b (FImage fields b), RMapCompat fields)
=> Rec (Tagged fields :. FieldRepr) b
-> JsonRepr ('SchemaObject fields)
withRepr :: Constructor a
withRepr = ReprObject . rmap (unTagged . getCompose) . fcast
class Representable s where
constructField :: Sing fn -> Proxy s -> Repr s -> FieldRepr '(fn, s)
instance SingI so => Representable ('SchemaObject so) where
constructField sfn _ o = withKnownSymbol sfn $ FieldRepr $ ReprObject o
instance (SingI cs, SingI sa) => Representable ('SchemaArray cs sa) where
constructField sfn _ a = withKnownSymbol sfn $ FieldRepr $ ReprArray a
instance SingI cs => Representable ('SchemaText cs) where
constructField sfn _ t = withKnownSymbol sfn $ FieldRepr $ ReprText t
instance SingI cs => Representable ('SchemaNumber cs) where
constructField sfn _ n = withKnownSymbol sfn $ FieldRepr $ ReprNumber n
instance Representable 'SchemaBoolean where
constructField sfn _ b = withKnownSymbol sfn $ FieldRepr $ ReprBoolean b
instance SingI so => Representable ('SchemaOptional so) where
constructField sfn _ o = withKnownSymbol sfn $ FieldRepr $ ReprOptional o
instance SingI (h ': tl) => Representable ('SchemaUnion (h ': tl)) where
constructField sfn _ u = withKnownSymbol sfn $ FieldRepr $ ReprUnion u
construct :: Sing s -> Repr s -> JsonRepr s
construct s r = case s of
SSchemaObject _ -> ReprObject r
SSchemaArray _ _ -> ReprArray r
SSchemaText _ -> ReprText r
SSchemaNumber _ -> ReprNumber r
SSchemaBoolean -> ReprBoolean r
SSchemaOptional _ -> ReprOptional r
SSchemaNull -> ReprNull
SSchemaUnion ss -> case ss of
SNil -> error "unconstructable union"
SCons _ _ -> ReprUnion r
type family FieldsOf (s :: Schema) :: [(Symbol, Schema)] where
FieldsOf ('SchemaObject fs) = fs
type FieldConstructor fn =
forall byField fs. (byField ~ ByField fn fs (FIndex fn fs), Representable byField)
=> Repr byField
-> (Tagged fs :. FieldRepr) '(fn, byField)
field :: forall fn. KnownSymbol fn => FieldConstructor fn
field = Compose . Tagged . constructField (sing :: Sing fn) Proxy
type family Repr (s :: Schema) = (ty :: Type) where
Repr ('SchemaObject so) = Rec FieldRepr so
Repr ('SchemaArray cs sa) = V.Vector (JsonRepr sa)
Repr ('SchemaText cs) = Text
Repr ('SchemaNumber cs) = Scientific
Repr 'SchemaBoolean = Bool
Repr ('SchemaOptional so) = Maybe (JsonRepr so)
Repr ('SchemaUnion (h ': tl)) = Union JsonRepr (h ': tl)