@@ -1,6 +1,7 @@
11{-# LANGUAGE AllowAmbiguousTypes #-}
2−{-# LANGUAGE OverloadedLists #-}
3−{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE CPP #-}
3+{-# LANGUAGE OverloadedLists #-}
4+{-# LANGUAGE OverloadedStrings #-}
45{-# OPTIONS_GHC -fprint-explicit-kinds #-}
56
67module Data.Schematic.Schema where
@@ -12,6 +13,7 @@ import Data.Aeson.Types as J
1213import Data.HashMap.Strict as H
1314import Data.Kind
1415import Data.Maybe
16+import Data.Schematic.Generator
1517import Data.Schematic.Instances ()
1618import Data.Scientific
1719import Data.Singletons.Prelude.List hiding (All, Union)
@@ -24,7 +26,8 @@ import Data.Vinyl hiding (Dict)
2426import qualified Data.Vinyl.TypeLevel as V
2527import GHC.Exts
2628import GHC.Generics (Generic)
27−import GHC.TypeLits (SomeNat(..), SomeSymbol(..), someSymbolVal, someNatVal)
29+import GHC.TypeLits
30+ (SomeNat(..), SomeSymbol(..), someNatVal, someSymbolVal)
2831import Prelude as P
2932import Test.SmallCheck.Series
3033
@@ -56,25 +59,25 @@ instance SingKind TextConstraint where
5659 STRegex s -> withKnownSymbol s (DTRegex $ T.pack $ symbolVal s)
5760 STEnum s -> let
5861 d :: Sing (s :: [Symbol]) -> [Text]
59− d SNil = []
62+ d SNil = []
6063 d (SCons ss@SSym fs) = T.pack (symbolVal ss) : d fs
6164 in DTEnum $ d s
6265 toSing = \case
6366 DTEq n -> case someNatVal n of
6467 Just (SomeNat (_ :: Proxy n)) -> SomeSing (STEq (SNat :: Sing n))
65− Nothing -> error "Negative singleton nat"
68+ Nothing -> error "Negative singleton nat"
6669 DTLt n -> case someNatVal n of
6770 Just (SomeNat (_ :: Proxy n)) -> SomeSing (STLt (SNat :: Sing n))
68− Nothing -> error "Negative singleton nat"
71+ Nothing -> error "Negative singleton nat"
6972 DTLe n -> case someNatVal n of
7073 Just (SomeNat (_ :: Proxy n)) -> SomeSing (STLe (SNat :: Sing n))
71− Nothing -> error "Negative singleton nat"
74+ Nothing -> error "Negative singleton nat"
7275 DTGt n -> case someNatVal n of
7376 Just (SomeNat (_ :: Proxy n)) -> SomeSing (STGt (SNat :: Sing n))
74− Nothing -> error "Negative singleton nat"
77+ Nothing -> error "Negative singleton nat"
7578 DTGe n -> case someNatVal n of
7679 Just (SomeNat (_ :: Proxy n)) -> SomeSing (STGe (SNat :: Sing n))
77− Nothing -> error "Negative singleton nat"
80+ Nothing -> error "Negative singleton nat"
7881 DTRegex s -> case someSymbolVal (T.unpack s) of
7982 SomeSymbol (_ :: Proxy n) -> SomeSing (STRegex (SSym :: Sing n))
8083 DTEnum ss -> case toSing ss of
@@ -161,43 +164,79 @@ instance SingKind NumberConstraint where
161164 toSing = \case
162165 DNEq n -> case someNatVal n of
163166 Just (SomeNat (_ :: Proxy n)) -> SomeSing (SNEq (SNat :: Sing n))
164− Nothing -> error "Negative singleton nat"
167+ Nothing -> error "Negative singleton nat"
165168 DNGt n -> case someNatVal n of
166169 Just (SomeNat (_ :: Proxy n)) -> SomeSing (SNGt (SNat :: Sing n))
167− Nothing -> error "Negative singleton nat"
170+ Nothing -> error "Negative singleton nat"
168171 DNGe n -> case someNatVal n of
169172 Just (SomeNat (_ :: Proxy n)) -> SomeSing (SNGe (SNat :: Sing n))
170− Nothing -> error "Negative singleton nat"
173+ Nothing -> error "Negative singleton nat"
171174 DNLt n -> case someNatVal n of
172175 Just (SomeNat (_ :: Proxy n)) -> SomeSing (SNLt (SNat :: Sing n))
173− Nothing -> error "Negative singleton nat"
176+ Nothing -> error "Negative singleton nat"
174177 DNLe n -> case someNatVal n of
175178 Just (SomeNat (_ :: Proxy n)) -> SomeSing (SNLe (SNat :: Sing n))
176− Nothing -> error "Negative singleton nat"
179+ Nothing -> error "Negative singleton nat"
177180
178181data ArrayConstraint
179182 = AEq Nat
183+ | AGt Nat
184+ | AGe Nat
185+ | ALt Nat
186+ | ALe Nat
180187 deriving (Generic)
181188
182189data DemotedArrayConstraint
183190 = DAEq Integer
191+ | DAGt Integer
192+ | DAGe Integer
193+ | DALt Integer
194+ | DALe Integer
184195 deriving (Generic, Eq, Show)
185196
186197data instance Sing (ac :: ArrayConstraint) where
187198 SAEq :: Sing n -> Sing ('AEq n)
199+ SAGt :: Sing n -> Sing ('AGt n)
200+ SAGe :: Sing n -> Sing ('AGe n)
201+ SALt :: Sing n -> Sing ('ALt n)
202+ SALe :: Sing n -> Sing ('ALe n)
188203
189204instance KnownNat n => SingI ('AEq n) where sing = SAEq sing
205+instance KnownNat n => SingI ('AGt n) where sing = SAGt sing
206+instance KnownNat n => SingI ('AGe n) where sing = SAGe sing
207+instance KnownNat n => SingI ('ALt n) where sing = SALt sing
208+instance KnownNat n => SingI ('ALe n) where sing = SALe sing
190209
191210instance Eq (Sing ('AEq n)) where _ == _ = True
211+instance Eq (Sing ('AGt n)) where _ == _ = True
212+instance Eq (Sing ('AGe n)) where _ == _ = True
213+instance Eq (Sing ('ALt n)) where _ == _ = True
214+instance Eq (Sing ('ALe n)) where _ == _ = True
192215
193216instance SingKind ArrayConstraint where
194217 type Demote ArrayConstraint = DemotedArrayConstraint
195218 fromSing = \case
196219 SAEq n -> withKnownNat n (DAEq . fromIntegral $ natVal n)
220+ SAGt n -> withKnownNat n (DAGt . fromIntegral $ natVal n)
221+ SAGe n -> withKnownNat n (DAGe . fromIntegral $ natVal n)
222+ SALt n -> withKnownNat n (DALt . fromIntegral $ natVal n)
223+ SALe n -> withKnownNat n (DALe . fromIntegral $ natVal n)
197224 toSing = \case
198225 DAEq n -> case someNatVal n of
199226 Just (SomeNat (_ :: Proxy n)) -> SomeSing (SAEq (SNat :: Sing n))
200− Nothing -> error "Negative singleton nat"
227+ Nothing -> error "Negative singleton nat"
228+ DAGt n -> case someNatVal n of
229+ Just (SomeNat (_ :: Proxy n)) -> SomeSing (SAGt (SNat :: Sing n))
230+ Nothing -> error "Negative singleton nat"
231+ DAGe n -> case someNatVal n of
232+ Just (SomeNat (_ :: Proxy n)) -> SomeSing (SAGe (SNat :: Sing n))
233+ Nothing -> error "Negative singleton nat"
234+ DALt n -> case someNatVal n of
235+ Just (SomeNat (_ :: Proxy n)) -> SomeSing (SALt (SNat :: Sing n))
236+ Nothing -> error "Negative singleton nat"
237+ DALe n -> case someNatVal n of
238+ Just (SomeNat (_ :: Proxy n)) -> SomeSing (SALe (SNat :: Sing n))
239+ Nothing -> error "Negative singleton nat"
201240
202241data Schema
203242 = SchemaText [TextConstraint]
@@ -334,6 +373,31 @@ data JsonRepr :: Schema -> Type where
334373 ReprOptional :: Maybe (JsonRepr s) -> JsonRepr ('SchemaOptional s)
335374 ReprUnion :: Union JsonRepr (h ': tl) -> JsonRepr ('SchemaUnion (h ': tl))
336375
376+instance (Monad m, Serial m Text, SingI cs)
377+ => Serial m (JsonRepr ('SchemaText cs)) where
378+ series = decDepth $ fmap ReprText $ textSeries $ fromSing (sing :: Sing cs)
379+
380+instance (Monad m, Serial m Scientific, SingI cs)
381+ => Serial m (JsonRepr ('SchemaNumber cs)) where
382+ series = decDepth $ fmap ReprNumber
383+ $ numberSeries $ fromSing (sing :: Sing cs)
384+
385+instance Monad m => Serial m (JsonRepr 'SchemaNull) where
386+ series = cons0 ReprNull
387+
388+instance (Serial m (JsonRepr s), Serial m (V.Vector (JsonRepr s)), SingI cs)
389+ => Serial m (JsonRepr ('SchemaArray cs s)) where
390+ series = decDepth $ fmap ReprArray
391+ $ arraySeries $ fromSing (sing :: Sing cs)
392+
393+instance (Serial m (JsonRepr s))
394+ => Serial m (JsonRepr ('SchemaOptional s)) where
395+ series = cons1 ReprOptional
396+
397+instance (Monad m, Serial m (Rec FieldRepr fs))
398+ => Serial m (JsonRepr ('SchemaObject fs)) where
399+ series = cons1 ReprObject
400+
337401-- | Move to the union package
338402instance Show (JsonRepr ('SchemaText cs)) where
339403 show (ReprText t) = "ReprText " P.++ show t
@@ -341,39 +405,31 @@ instance Show (JsonRepr ('SchemaText cs)) where
341405instance Show (JsonRepr ('SchemaNumber cs)) where
342406 show (ReprNumber n) = "ReprNumber " P.++ show n
343407
408+instance Show (JsonRepr 'SchemaBoolean) where
409+ show (ReprBoolean n) = "ReprBoolean " P.++ show n
410+
344411instance Show (JsonRepr 'SchemaNull) where show _ = "ReprNull"
345412
346413instance Show (JsonRepr s) => Show (JsonRepr ('SchemaArray acs s)) where
347414 show (ReprArray v) = "ReprArray " P.++ show v
348415
416+#if MIN_VERSION_base(4,12,0)
417+instance
418+ ( V.RecAll FieldRepr fs Show, RMap fs, ReifyConstraint Show FieldRepr fs
419+ , RecordToList fs )
420+ => Show (JsonRepr ('SchemaObject fs)) where
421+ show (ReprObject fs) = "ReprObject " P.++ show fs
422+#else
349423instance V.RecAll FieldRepr fs Show => Show (JsonRepr ('SchemaObject fs)) where
350424 show (ReprObject fs) = "ReprObject " P.++ show fs
425+#endif
351426
352427instance Show (JsonRepr s) => Show (JsonRepr ('SchemaOptional s)) where
353428 show (ReprOptional s) = "ReprOptional " P.++ show s
354429
355−instance (Monad m, Serial m Text)
356− => Serial m (JsonRepr ('SchemaText cs)) where
357− series = cons1 ReprText
358−
359−instance (Monad m, Serial m Scientific)
360− => Serial m (JsonRepr ('SchemaNumber cs)) where
361− series = cons1 ReprNumber
362−
363−instance Monad m => Serial m (JsonRepr 'SchemaNull) where
364− series = cons0 ReprNull
365−
366−instance (Serial m (V.Vector (JsonRepr s)))
367− => Serial m (JsonRepr ('SchemaArray cs s)) where
368− series = cons1 ReprArray
369−
370−instance (Serial m (JsonRepr s))
371− => Serial m (JsonRepr ('SchemaOptional s)) where
372− series = cons1 ReprOptional
373−
374−instance (Monad m, Serial m (Rec FieldRepr fs))
375− => Serial m (JsonRepr ('SchemaObject fs)) where
376− series = cons1 ReprObject
430+instance Show (Union JsonRepr (h ': tl))
431+ => Show (JsonRepr ('SchemaUnion (h ': tl))) where
432+ show (ReprUnion s) = "ReprUnion " P.++ show s
377433
378434instance Eq (Rec FieldRepr fs) => Eq (JsonRepr ('SchemaObject fs)) where
379435 ReprObject a == ReprObject b = a == b
@@ -384,6 +440,9 @@ instance Eq (JsonRepr ('SchemaText cs)) where
384440instance Eq (JsonRepr ('SchemaNumber cs)) where
385441 ReprNumber a == ReprNumber b = a == b
386442
443+instance Eq (JsonRepr 'SchemaBoolean) where
444+ ReprBoolean a == ReprBoolean b = a == b
445+
387446instance Eq (JsonRepr 'SchemaNull) where
388447 ReprNull == ReprNull = True
389448
@@ -393,6 +452,10 @@ instance Eq (JsonRepr s) => Eq (JsonRepr ('SchemaArray as s)) where
393452instance Eq (JsonRepr s) => Eq (JsonRepr ('SchemaOptional s)) where
394453 ReprOptional a == ReprOptional b = a == b
395454
455+instance Eq (Union JsonRepr (h ': tl))
456+ => Eq (JsonRepr ('SchemaUnion (h ': tl))) where
457+ ReprUnion a == ReprUnion b = a == b
458+
396459instance Ord (Rec FieldRepr fs) => Ord (JsonRepr ('SchemaObject fs)) where
397460 ReprObject a `compare` ReprObject b = a `compare` b
398461
@@ -402,6 +465,9 @@ instance Ord (JsonRepr ('SchemaText cs)) where
402465instance Ord (JsonRepr ('SchemaNumber cs)) where
403466 ReprNumber a `compare` ReprNumber b = a `compare` b
404467
468+instance Ord (JsonRepr 'SchemaBoolean) where
469+ ReprBoolean a `compare` ReprBoolean b = a `compare` b
470+
405471instance Ord (JsonRepr 'SchemaNull) where
406472 compare _ _ = EQ
407473
@@ -411,6 +477,10 @@ instance Ord (JsonRepr s) => Ord (JsonRepr ('SchemaArray as s)) where
411477instance Ord (JsonRepr s) => Ord (JsonRepr ('SchemaOptional s)) where
412478 ReprOptional a `compare` ReprOptional b = a `compare` b
413479
480+instance Ord (Union JsonRepr (h ': tl))
481+ => Ord (JsonRepr ('SchemaUnion (h ': tl))) where
482+ ReprUnion a `compare` ReprUnion b = a `compare` b
483+
414484instance IsList (JsonRepr ('SchemaArray cs s)) where
415485 type Item (JsonRepr ('SchemaArray cs s)) = JsonRepr s
416486 fromList = ReprArray . GHC.Exts.fromList
@@ -502,7 +572,7 @@ instance J.ToJSON (JsonRepr a) where
502572 toJSON (ReprText t) = J.String t
503573 toJSON (ReprNumber n) = J.Number n
504574 toJSON (ReprOptional s) = case s of
505− Just v -> toJSON v
575+ Just v -> toJSON v
506576 Nothing -> J.Null
507577 toJSON (ReprArray v) = J.Array $ toJSON <$> v
508578 toJSON (ReprObject r) = J.Object . H.fromList . fold $ r