on 6746298 help sign in
4 files changed+47−37
since splitsnapshots
unifiedsplit
README.md+3−3 schematic.cabal+2−2 src/Data/Schematic/Instances.hs+5−6 src/Data/Schematic/Schema.hs+37−26
README.md+3−3
@@ -6,10 +6,10 @@
66
77The goal of the library is to provide a type-safe transport layer for serializing and validating JSON. It can be thought of as a subset of [json-schema](http://json-schema.org), which is basically a specification of a JSON document. The other goal is getting as much as possible from this specification for free. Right now the following bits are prototyped:
88
9−* All the instantiations of transport types are structurally follow the schema provided by user
10−* Serializers are generic, so they follow from the type-level schema and the're supposed to have roundtrip property by implementation.
9+* All of the instantiations of the transport types structurally follow the schema provided by user
10+* Serializers are generic, so they follow from the type-level schema and the're supposed to have a roundtrip property by an implementation.
1111* Runtime value validators are generated from the schema. Validation errors are reported as a pairs of a json-path to the element and an error message.
12−* There are migrations. It's possible to describe a series of migrations to the schema and have all the machinery deserialize a user specified version of the schema if there's a few versions.
12+* There are migrations. It's possible to describe a series of migrations to the schema and have all the necessary machinery to deserialize a user specified version of the schema if there's a few versions.
1313
1414## TODO
1515
schematic.cabal+2−2
@@ -66,12 +66,12 @@ library
6666 , singletons
6767 , smallcheck
6868 , smallcheck-series
69+ , superrecord
6970 , tagged
7071 , text
7172 , unordered-containers
7273 , validationt >= 0.1.0.1
7374 , vector
74− , vinyl
7575 hs-source-dirs: src
7676 default-language: Haskell2010
7777
@@ -120,10 +120,10 @@ test-suite spec
120120 , smallcheck
121121 , smallcheck-series
122122 , singletons
123+ , superrecord
123124 , tagged
124125 , text
125126 , unordered-containers
126127 , validationt >= 0.1.0.1
127− , vinyl
128128 other-modules: SchemaSpec
129129 , LensSpec
src/Data/Schematic/Instances.hs+5−6
@@ -5,16 +5,15 @@ module Data.Schematic.Instances where
55
66import Data.Scientific
77import Data.Vector as V
8−import Data.Vinyl
98import Test.SmallCheck.Series
109
1110
12−instance Monad m => Serial m (Rec f '[]) where
13− series = cons0 RNil
11+-- instance Monad m => Serial m (Rec f '[]) where
12+-- series = cons0 RNil
1413
15−instance (Serial m (f a), Serial m (Rec f as), Monad m)
16− => Serial m (Rec f (a ': as)) where
17− series = cons2 (:&)
14+-- instance (Serial m (f a), Serial m (Rec f as), Monad m)
15+-- => Serial m (Rec f (a ': as)) where
16+-- series = cons2 (:&)
1817
1918instance Serial m a => Serial m (V.Vector a) where
2019 series = V.fromList <$> series
src/Data/Schematic/Schema.hs+37−26
@@ -5,25 +5,24 @@
55
66module Data.Schematic.Schema where
77
8−import Control.Applicative ()
9−import Control.Monad
10−import Data.Aeson as J
11−import Data.Aeson.Types as J
12−import Data.HashMap.Strict as H
13−import Data.Kind
14−import Data.Maybe
15−import Data.Schematic.Instances ()
16−import Data.Scientific
17−import Data.Singletons.Prelude.List hiding (All)
18−import Data.Singletons.TH
19−import Data.Singletons.TypeLits
20−import Data.Text as T
21−import Data.Vector as V
22−import Data.Vinyl hiding (Dict)
23−import qualified Data.Vinyl.TypeLevel as V
24−import GHC.Generics (Generic)
25−import Prelude as P
26−import Test.SmallCheck.Series
8+import Control.Applicative ()
9+import Control.Monad
10+import Data.Aeson as J
11+import Data.Aeson.Types as J
12+import Data.HashMap.Strict as H
13+import Data.Kind
14+import Data.Maybe
15+import Data.Schematic.Instances ()
16+import Data.Scientific
17+import Data.Singletons.Prelude.List hiding (All)
18+import Data.Singletons.TH
19+import Data.Singletons.TypeLits
20+import Data.Text as T
21+import Data.Vector as V
22+import GHC.Generics (Generic)
23+import Prelude as P
24+import SuperRecord
25+import Test.SmallCheck.Series
2726
2827
2928type family All (c :: k -> Constraint) (s :: [k]) :: Constraint where
@@ -166,12 +165,18 @@ instance
166165 => Serial m (FieldRepr '(name, schema)) where
167166 series = FieldRepr <$> series
168167
168+type family Fields (ts :: [u]) :: [] where
169+ Fields '[] = '[]
170+ Fields (t ': ts) = (FieldRepr t ': Fields ts)
171+
172+type JObject ts = Rec (Fields ts)
173+
169174data JsonRepr :: Schema -> Type where
170175 ReprText :: Text -> JsonRepr ('SchemaText cs)
171176 ReprNumber :: Scientific -> JsonRepr ('SchemaNumber cs)
172177 ReprNull :: JsonRepr 'SchemaNull
173178 ReprArray :: V.Vector (JsonRepr s) -> JsonRepr ('SchemaArray cs s)
174− ReprObject :: Rec FieldRepr fs -> JsonRepr ('SchemaObject fs)
179+ ReprObject :: JObject fs -> JsonRepr ('SchemaObject fs)
175180 ReprOptional :: Maybe (JsonRepr s) -> JsonRepr ('SchemaOptional s)
176181
177182instance Show (JsonRepr ('SchemaText cs)) where
@@ -185,7 +190,12 @@ instance Show (JsonRepr 'SchemaNull) where show _ = "ReprNull"
185190instance Show (JsonRepr s) => Show (JsonRepr ('SchemaArray acs s)) where
186191 show (ReprArray v) = "ReprArray " P.++ show v
187192
188−instance V.RecAll FieldRepr fs Show => Show (JsonRepr ('SchemaObject fs)) where
193+-- There's a PR in the superrecord library, remove it if gets merged.
194+type family RecAll (c :: u -> Constraint) (rs :: [u]) :: Constraint where
195+ RecAll c '[] = ()
196+ RecAll c (r ': rs) = (c r, RecAll c rs)
197+
198+instance RecAll Show fs => Show (JsonRepr ('SchemaObject fs)) where
189199 show (ReprObject fs) = "ReprObject " P.++ show fs
190200
191201instance Show (JsonRepr s) => Show (JsonRepr ('SchemaOptional s)) where
@@ -210,11 +220,11 @@ instance (Serial m (JsonRepr s))
210220 => Serial m (JsonRepr ('SchemaOptional s)) where
211221 series = cons1 ReprOptional
212222
213−instance (Monad m, Serial m (Rec FieldRepr fs))
223+instance (Monad m, Serial m (JObject fs))
214224 => Serial m (JsonRepr ('SchemaObject fs)) where
215225 series = cons1 ReprObject
216226
217−instance Eq (Rec FieldRepr fs) => Eq (JsonRepr ('SchemaObject fs)) where
227+instance Eq (JObject fs) => Eq (JsonRepr ('SchemaObject fs)) where
218228 ReprObject a == ReprObject b = a == b
219229
220230instance Eq (JsonRepr ('SchemaText cs)) where
@@ -251,7 +261,7 @@ instance SingI schema => J.FromJSON (JsonRepr schema) where
251261 $ withArray "Array" (fmap ReprArray . traverse parseJSON) value
252262 SSchemaObject fs -> do
253263 let
254− demoteFields :: SList s -> H.HashMap Text J.Value -> Parser (Rec FieldRepr s)
264+ demoteFields :: SList s -> H.HashMap Text J.Value -> Parser (JObject s)
255265 demoteFields SNil _ = pure RNil
256266 demoteFields (SCons (STuple2 (n :: Sing fn) s) tl) h = withKnownSymbol n $ do
257267 let fieldName = T.pack $ symbolVal (Proxy @fn)
@@ -287,11 +297,12 @@ instance J.ToJSON (JsonRepr a) where
287297 toJSON (ReprArray v) = J.Array $ toJSON <$> v
288298 toJSON (ReprObject r) = J.Object . H.fromList . fold $ r
289299 where
290− extract :: forall name s . (KnownSymbol name)
300+ extract
301+ :: forall name s . (KnownSymbol name)
291302 => FieldRepr '(name, s)
292303 -> (Text, Value)
293304 extract (FieldRepr s) = (T.pack $ symbolVal $ Proxy @name, toJSON s)
294− fold :: Rec FieldRepr fs -> [(Text, J.Value)]
305+ fold :: JObject fs -> [(Text, J.Value)]
295306 fold = \case
296307 RNil -> []
297308 fr@(FieldRepr _) :& tl -> (extract fr) : fold tl