@@ -15,7 +15,6 @@ import Data.Text (Text)
15import Data.Type.Equality
15import Data.Type.Equality
16import Data.Vinyl
16import Data.Vinyl
17import Data.Vinyl.Functor
17import Data.Vinyl.Functor
19import GHC.TypeLits (KnownNat, natVal, KnownSymbol, symbolVal, Symbol, Nat)
18import GHC.TypeLits (KnownNat, natVal, KnownSymbol, symbolVal, Symbol, Nat)
@@ -27,6 +26,7 @@ data JType
30type family Repr (ty :: JType) :: * where
30type family Repr (ty :: JType) :: * where
31 Repr 'JText = String -- because of matchRegex
31 Repr 'JText = String -- because of matchRegex
32 Repr 'JNumber = Double
32 Repr 'JNumber = Double
@@ -34,47 +34,53 @@ type family Repr (ty :: JType) :: * where
34class Constrained (ty :: JType) c where
34class Constrained (ty :: JType) c where
35 cRep :: Proxy ty -> Proxy c -> CRepr ty
35 cRep :: Proxy ty -> Proxy c -> CRepr ty
37data LengthEqNat nat
39data LengthEqNat nat
39instance KnownNat nat => Constrained 'JText (LengthEqNat nat) where
41instance KnownNat nat => Constrained 'JText (LengthEqNat nat) where
40 cRep _ _ = LengthEq $ natVal (Proxy @nat)
42 cRep _ _ = LengthEq $ natVal (Proxy @nat)
42−data Field field jty schema
44+data Gt nat
46+instance KnownNat nat => Constrained 'JNumber (Gt nat) where
47+ cRep _ _ = Gt $ natVal (Proxy @nat)
51+data Field field ty schema
44−instance (Schematic jty, Verifiable (JT jty) cs, KnownSymbol field)
53+instance (SchemaConstructor (JT jty), Verifiable (JT jty) cs, KnownSymbol field)
45− => Constrained JObject (Field field jty cs) where
54+ => Constrained JObject (Field field ty cs) where
46 cRep _ _ =
55 cRep _ _ =
47− (symbolVal (Proxy @field), constructor (Proxy @jty) $ schema (Proxy @(JT jty)) (Proxy @cs))
56+ (symbolVal (Proxy @field), constructor (Proxy @(JT jty))
57+ $ schema (Proxy @(JT jty)) (Proxy @cs))
49class Verifiable ty cs where
61class Verifiable ty cs where
50 schema :: Proxy ty -> Proxy cs -> [CRepr ty]
62 schema :: Proxy ty -> Proxy cs -> [CRepr ty]
52−instance Verifiable JText '[] where
56− (Constrained JText c, Verifiable JText cs) => Verifiable JText (c ': cs) where
65+ (Constrained 'JText c, Verifiable 'JText cs) => Verifiable 'JText (c ': cs) where
57− schema _ _ = schema (Proxy @JText) (Proxy @cs) ++ schema (Proxy @JText) (Proxy @cs)
66+ schema _ _ = cRep (Proxy @'JText) (Proxy @c) : schema (Proxy @'JText) (Proxy @cs)
59−instance Verifiable JNumber '[] where
63− (Constrained JNumber c, Verifiable JNumber cs) => Verifiable JNumber (c ': cs) where
69+ (Constrained 'JNumber c, Verifiable 'JNumber cs) => Verifiable 'JNumber (c ': cs) where
64− schema _ _ = schema (Proxy @JNumber) (Proxy @cs) ++ schema (Proxy @JNumber) (Proxy @cs)
70+ schema _ _ = cRep (Proxy @'JNumber) (Proxy @c) : schema (Proxy @'JNumber) (Proxy @cs)
66−instance Verifiable JObject '[] where
72+instance Verifiable jty '[] where
67 schema _ _ = []
73 schema _ _ = []
70− (Constrained JObject c, Verifiable JObject cs, KnownSymbol field)
76+ (Constrained 'JObject c, Verifiable 'JObject cs, KnownSymbol field)
71− => Verifiable JObject ((Field field jty c) ': cs) where
77+ => Verifiable 'JObject ((Field field jty c) ': cs) where
72− schema _ _ = cRep (Proxy @JObject) (Proxy @c) : schema (Proxy @JObject) (Proxy @cs)
78+ schema _ _ = cRep (Proxy @'JObject) (Proxy @c) : schema (Proxy @'JObject) (Proxy @cs)
74−type family VerifiableFields (ty :: JType) (els :: [k]) :: Constraint where
80+-- type family VerifiableFields (ty :: JType) (els :: [k]) :: Constraint where
75− VerifiableFields ty '[] = ()
81+-- VerifiableFields ty '[] = ()
76− VerifiableFields ty ((Field f jty s) ': elss)
82+-- VerifiableFields ty ((Field f jty s) ': elss)
77− = (Constrained jty s, VerifiableFields ty elss)
83+-- = (Verifiable jty s, VerifiableFields ty elss)
79type family CRepr (jty :: JType) :: * where
85type family CRepr (jty :: JType) :: * where
80 CRepr JText = TextConstraint
86 CRepr JText = TextConstraint
@@ -85,54 +91,84 @@ data TextConstraint
85 = LengthEq Integer
91 = LengthEq Integer
86 | LengthLe Integer
92 | LengthLe Integer
87 | LengthGt Integer
93 | LengthGt Integer
89data NumberConstraint
96data NumberConstraint
90 = Le Integer
97 = Le Integer
91 | Gt Integer
98 | Gt Integer
92 | Eq Integer
99 | Eq Integer
94data Schema
102data Schema
95 = SchemaText [TextConstraint]
103 = SchemaText [TextConstraint]
96 | SchemaNumber [NumberConstraint]
104 | SchemaNumber [NumberConstraint]
97 | SchemaObject [(String, Schema)]
105 | SchemaObject [(String, Schema)]
98 | SchemaArray Schema
106 | SchemaArray Schema
100-- | Apply constraint for each element of list
109-- | Apply constraint for each element of list
101type family AllSatisfy (c :: k -> Constraint) (s :: [k]) :: Constraint where
110type family AllSatisfy (c :: k -> Constraint) (s :: [k]) :: Constraint where
102 AllSatisfy c '[] = ()
111 AllSatisfy c '[] = ()
103 AllSatisfy c (a ': as) = (c a, AllSatisfy c as)
112 AllSatisfy c (a ': as) = (c a, AllSatisfy c as)
114+class SchemaConstructor jty where
115+ constructor :: Proxy jty -> [CRepr jty] -> Schema
117+instance SchemaConstructor 'JText where
118+ constructor _ = SchemaText
120+instance SchemaConstructor 'JNumber where
121+ constructor _ = SchemaNumber
123+instance SchemaConstructor 'JObject where
124+ constructor _ = SchemaObject
105−class Schematic ty where
126+class (SchemaConstructor (JT ty)) => Schematic ty where
106− type JT ty :: JType
127+ type JT (ty :: k) :: JType
107− constructor :: Proxy ty -> [CRepr (JT ty)] -> Schema
128+ build :: Proxy ty -> Schema
109data SText cs
130data SText cs
111−instance (Verifiable JText cs) => Schematic (SText cs) where
132+instance (Verifiable 'JText cs) => Schematic (SText cs) where
112− type JT (SText cs) = JText
133+ type JT (SText cs) = 'JText
113− constructor _ = SchemaText
134+ build _ = constructor (Proxy @(JT (SText cs))) $ schema (Proxy @JText) (Proxy @cs)
115-- example
136-- example
116type TextSchema = SText '[LengthEqNat 3]
137type TextSchema = SText '[LengthEqNat 3]
118data SNumber cs
139data SNumber cs
120−instance (Verifiable JNumber cs) => Schematic (SNumber cs) where
141+instance (Verifiable 'JNumber cs) => Schematic (SNumber cs) where
121− type JT (SNumber cs) = JNumber
142+ type JT (SNumber cs) = 'JNumber
122− constructor _ = SchemaNumber
143+ build _ = constructor (Proxy @(JT (SNumber cs))) $ schema (Proxy @'JNumber) (Proxy @cs)
146+type NumberSchema = SNumber '[ Gt 3]
148+instance (Verifiable (JT ty) cs, SchemaConstructor (JT ty)) => Schematic (Field field ty cs) where
149+ type JT (Field field ty cs) = JT ty
150+ build _ = constructor (Proxy @(JT (Field field ty cs)))
151+ $ schema (Proxy @(JT (Field field ty cs))) (Proxy @cs)
124data SObject els
153data SObject els
126−instance (els ~ '[k], AllSatisfy Schematic els) => Schematic (SObject els) where
155+instance (els ~ '[k], Verifiable 'JObject els, AllSatisfy Schematic els)
156+ => Schematic (SObject els) where
127− type JT (SObject els) = JObject
157+ type JT (SObject els) = 'JObject
128− constructor _ = SchemaObject
158+ build _ =
159+ constructor (Proxy @(JT (SObject els)))
160+ $ schema (Proxy @(JT (SObject els))) (Proxy @els)
130-- | Shows it's top-level definition according to the json-schema
162-- | Shows it's top-level definition according to the json-schema
131class TopLevel spec
163class TopLevel spec
133−instance Schematic (SObject spec) => TopLevel (SObject els)
165+instance Schematic (SObject els) => TopLevel (SObject els)
135−-- toSchema :: forall spec cs. (Schematic spec, VerifiableFields (JT spec), TopLevel spec) => Proxy spec -> Schema
167+-- | TODO: abstract over objects and arrays
169+-- :: forall els (e :: [k]). (e ~ '[], Verifiable (JT (SObject els)) e, Schematic (SObject els))
170+-- => Proxy (SObject els)
136−-- toSchema pspec = constructor pspec $ schema (Proxy @(JT spec)) pspec
172+-- toSchema p = constructor p $ schema (Proxy @(JT (SObject els))) (Proxy @els)
138−type TestStruct = SObject '[ '("carrier", [SText '[LengthEqNat 3]]) ]
174+type TestStruct = SObject '[ Field "carrier" 'JText [SText '[LengthEqNat 3] ] ]