on master help sign in
Object lenses
commit585f72b82a0813c74fa754f47846f9ee65c9054b authorDenis Redozubov <denis.redozubov@gmail.com> dateSun 11 Jun 2017, 14:31 (9 years ago) parenta9972c3
4 files changed+101−22
schematic.cabal+2 src/Data/Schematic/Lens.hs+75 src/Data/Schematic/Migration.hs−1 src/Data/Schematic/Schema.hs+24−21
schematic.cabal+2
@@ -18,6 +18,7 @@ cabal-version: >=1.10
1818library
1919 exposed-modules: Data.Schematic
2020 , Data.Schematic.Instances
21+ , Data.Schematic.Lens
2122 , Data.Schematic.Migration
2223 , Data.Schematic.Path
2324 , Data.Schematic.Schema
@@ -52,6 +53,7 @@ library
5253 , TemplateHaskell
5354 , TypeApplications
5455 , TypeFamilies
56+ , TypeFamilyDependencies
5557 , TypeInType
5658 , TypeOperators
5759 , TypeSynonymInstances
src/Data/Schematic/Lens.hsnew file+75
@@ -0,0 +1,75 @@
1+{-# LANGUAGE UndecidableSuperClasses #-}
2+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3+{-# LANGUAGE AllowAmbiguousTypes #-}
4+{-# LANGUAGE InstanceSigs #-}
5+
6+module Data.Schematic.Lens where
7+
8+import Data.Proxy
9+import Data.Schematic.Migration
10+import Data.Schematic.Schema
11+import Data.Vinyl
12+import Data.Vinyl.Functor
13+import Data.Vinyl.TypeLevel (Nat(..))
14+import GHC.TypeLits (Symbol)
15+
16+
17+-- | A partial relation that gives the index of a value in a list.
18+type family FIndex (r :: Symbol) (rs :: [(Symbol, Schema)]) :: Nat where
19+ FIndex r ( '(fn, s) ': rs) = 'Z
20+ FIndex r ( s ': rs) = 'S (FIndex r rs)
21+
22+class i ~ FIndex fn rs => FElem (fn :: Symbol) (rs :: [(Symbol, Schema)]) (i :: Nat) where
23+ type ByRevision fn rs i :: Schema
24+ flens
25+ :: Functor g
26+ => proxy fn
27+ -> (FieldRepr '(fn, (ByRevision fn rs i)) -> g (FieldRepr '(fn, (ByRevision fn rs i))))
28+ -> Rec FieldRepr rs
29+ -> g (Rec FieldRepr rs)
30+
31+ -- | For Vinyl users who are not using the @lens@ package, we provide a getter.
32+ fget
33+ :: proxy fn
34+ -> Rec FieldRepr rs
35+ -> FieldRepr '(fn, (ByRevision fn rs i))
36+
37+ -- | For Vinyl users who are not using the @lens@ package, we also provide a
38+ -- setter. In general, it will be unambiguous what field is being written to,
39+ -- and so we do not take a proxy argument here.
40+ fput
41+ :: FieldRepr '(fn, ByRevision fn rs i)
42+ -> Rec FieldRepr rs
43+ -> Rec FieldRepr rs
44+
45+instance FElem fn ('(fn, r) ': rs) 'Z where
46+ type ByRevision fn ('(fn, r) ': rs) 'Z = r
47+ flens _ f (x :& xs) = fmap (:& xs) (f x)
48+ {-# INLINE flens #-}
49+ fget k = getConst . flens k Const
50+ {-# INLINE fget #-}
51+ fput y = getIdentity . flens Proxy (\_ -> Identity y)
52+ {-# INLINE fput #-}
53+
54+instance (FIndex r (s ': rs) ~ 'S i, FElem r rs i) => FElem r (s ': rs) ('S i) where
55+ type ByRevision fn (s ': rs) ('S i) = ByRevision fn rs i
56+ flens p f (x :& xs) = fmap (x :&) (flens p f xs)
57+ {-# INLINE flens #-}
58+ fget k = getConst . flens k Const
59+ {-# INLINE fget #-}
60+ fput y = getIdentity . flens Proxy (\_ -> Identity y)
61+ {-# INLINE fput #-}
62+
63+type SchemaExample
64+ = 'SchemaObject
65+ '[ '("foo", 'SchemaArray '[ 'AEq 1] ('SchemaNumber '[ 'NGt 10]))
66+ , '("bar", 'SchemaOptional ('SchemaText '[ 'TEnum '["foo", "bar"]]))]
67+
68+type TestMigration =
69+ 'Migration "test_revision"
70+ '[ 'Diff '[ 'PKey "bar" ] ('Update ('SchemaText '[]))
71+ , 'Diff '[ 'PKey "foo" ] ('Update ('SchemaNumber '[])) ]
72+
73+type VS = 'Versioned SchemaExample '[ TestMigration ]
74+
75+type Ex = FIndex "initial" (AllVersions VS)
src/Data/Schematic/Migration.hs−1
@@ -8,7 +8,6 @@ import Data.Schematic.Path
88import Data.Schematic.Schema
99import Data.Singletons.Prelude hiding (All)
1010import Data.Singletons.TypeLits
11−-- import Data.Vinyl hiding (Dict)
1211
1312
1413data Path
src/Data/Schematic/Schema.hs+24−21
@@ -5,26 +5,25 @@
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−
17−import Data.Scientific
18−import Data.Singletons.Prelude.List hiding (All)
19−import Data.Singletons.TH
20−import Data.Singletons.TypeLits
21−import Data.Text as T
22−import Data.Vector as V
23−import Data.Vinyl hiding (Dict)
24−import Data.Vinyl.TypeLevel hiding (Nat)
25−import GHC.Generics (Generic)
26−import Prelude as P
27−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 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
2827
2928
3029type family All (c :: k -> Constraint) (s :: [k]) :: Constraint where
@@ -137,6 +136,10 @@ data FieldRepr :: (Symbol, Schema) -> Type where
137136 => JsonRepr schema
138137 -> FieldRepr '(name, schema)
139138
139+-- | Forgetful Functor Ufr
140+toJsonRepr :: FieldRepr '(fn, sch) -> JsonRepr sch
141+toJsonRepr (FieldRepr x) = x
142+
140143knownFieldName
141144 :: forall proxy (fieldName :: Symbol) schema
142145 . KnownSymbol fieldName
@@ -182,7 +185,7 @@ instance Show (JsonRepr 'SchemaNull) where show _ = "ReprNull"
182185instance Show (JsonRepr s) => Show (JsonRepr ('SchemaArray acs s)) where
183186 show (ReprArray v) = "ReprArray " P.++ show v
184187
185−instance RecAll FieldRepr fs Show => Show (JsonRepr ('SchemaObject fs)) where
188+instance V.RecAll FieldRepr fs Show => Show (JsonRepr ('SchemaObject fs)) where
186189 show (ReprObject fs) = "ReprObject " P.++ show fs
187190
188191instance Show (JsonRepr s) => Show (JsonRepr ('SchemaOptional s)) where