-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Scalable anonymous records -- -- The large-anon package provides support for anonymous records -- in Haskell, with a focus on compile-time (and run-time) scalability. @package large-anon @version 0.2 -- | Restore "regular" environment when using RebindableSyntax -- -- The RebindableSyntax extension is currently required when -- using OverloadedRecordUpdate, but when using this extension, -- a number of functions are suddenly no longer in scope that normally -- are. This module restores those functions to their standard -- definition. module Data.Record.Anon.Overloading app :: ArrowApply a => a (a b c, b) c -- | Lift a function to an arrow. arr :: Arrow a => (b -> c) -> a b c -- | Send the first component of the input through the argument arrow, and -- copy the rest unchanged to the output. first :: Arrow a => a b c -> a (b, d) (c, d) loop :: ArrowLoop a => a (b, d) (c, d) -> a b c -- | Left-to-right composition (>>>) :: forall {k} cat (a :: k) (b :: k) (c :: k). Category cat => cat a b -> cat b c -> cat a c infixr 1 >>> -- | Fanin: Split the input between the two argument arrows and merge their -- outputs. -- -- The default definition may be overridden with a more efficient version -- if desired. (|||) :: ArrowChoice a => a b d -> a c d -> a (Either b c) d infixr 2 ||| fromString :: IsString a => String -> a fromLabel :: IsLabel x a => a -- | Selector function to extract the field from the record. getField :: HasField x r a => r -> a ifThenElse :: Bool -> a -> a -> a setField :: forall x r a. HasField x r a => r -> a -> r -- | Supporting definitions used by both the simple and the advanced -- interface -- -- To use the anonymous records library, you will want to use either the -- simple interface in Data.Record.Anon.Simple or the advanced -- interface in Data.Record.Anon.Advanced. This module -- provides definitions that are used by both. Moreover, unlike -- .Simple and .Advanced, this module is designed to be -- imported unqualified. A typical import section will therefore look -- something like -- --
--   import Data.Record.Anon
--   import Data.Record.Anon.Simple (Record)
--   import qualified Data.Record.Anon.Simple as Anon
--   
-- -- In addition, since the classes and type families defined here as -- handled by the plugin, you will also want to enable that: -- --
--   {-# OPTIONS_GHC -fplugin=Data.Record.Anon.Plugin #-}
--   
module Data.Record.Anon pattern (:=) :: () => a -> b -> Pair a b -- | Row: type-level list of field names and corresponding field types type Row k = [Pair Symbol k] -- | Merge two rows -- -- See merge for detailed discussion. type family Merge :: Row k -> Row k -> Row k -- | Require that c x holds for every (n := x) in -- r. class AllFields (r :: Row k) (c :: k -> Constraint) -- | Require that all field names in r are known class KnownFields (r :: Row k) -- | Subrecords -- -- If SubRow r r' holds, we can project (or create a lens) -- r to r'. See project for detailed discussion. class SubRow (r :: Row k) (r' :: Row k) -- | Specialized form of HasField -- -- RowHasField n r a holds if there is an (n := a) in -- r. class RowHasField (n :: Symbol) (r :: Row k) (a :: k) | n r -> a -- | Proxy for a field name, with IsLabel instance -- -- The IsLabel instance makes it possible to write -- --
--   #foo
--   
-- -- to mean -- --
--   Field (Proxy @"foo")
--   
data Field n -- | Symbol (type-level string) with compile-time computed hash -- -- Instances are computed on the fly by the plugin. class KnownHash (s :: Symbol) hashVal :: forall proxy. KnownHash s => proxy s -> Int -- | Type-level metadata -- --
--      FieldTypes Maybe [ "a" := Int, "b" := Bool ]
--   == [ '("a", Maybe Int), '("b", Maybe Bool) ]
--   
type family FieldTypes (f :: k -> Type) (r :: Row k) :: [(Symbol, Type)] -- | Like FieldTypes, but for the simple API (no functor argument) -- --
--      SimpleFieldTypes [ "a" := Int, "b" := Bool ]
--   == [ '("a", Int), '("b", Bool) ]
--   
type family SimpleFieldTypes (r :: Row Type) :: [(Symbol, Type)] -- | Existential type ("there exists an x such that f x") data Some (f :: k -> Type) [Some] :: forall k (f :: k -> Type) (x :: k). f x -> Some f -- | Evidence of some constraint c -- -- This is like Dict, but without the functor argument. data Reflected c [Reflected] :: c => Reflected c -- | Lifted product of functors. data Product (f :: k -> Type) (g :: k -> Type) (a :: k) Pair :: f a -> g a -> Product (f :: k -> Type) (g :: k -> Type) (a :: k) -- | Proxy is a type that holds no data, but has a phantom parameter -- of arbitrary type (or even kind). Its use is to provide type -- information, even though there is no value available of that type (or -- it may be too costly to create one). -- -- Historically, Proxy :: Proxy a is a safer -- alternative to the undefined :: a idiom. -- --
--   >>> Proxy :: Proxy (Void, Int -> Int)
--   Proxy
--   
-- -- Proxy can even hold types of higher kinds, -- --
--   >>> Proxy :: Proxy Either
--   Proxy
--   
-- --
--   >>> Proxy :: Proxy Functor
--   Proxy
--   
-- --
--   >>> Proxy :: Proxy complicatedStructure
--   Proxy
--   
data Proxy (t :: k) Proxy :: Proxy (t :: k) -- | Composition of functors. -- -- Like Compose, but kind-polymorphic and with a shorter name. newtype ( (f :: l -> Type) :.: (g :: k -> l) ) (p :: k) Comp :: f (g p) -> (:.:) (f :: l -> Type) (g :: k -> l) (p :: k) infixr 7 :.: -- | The identity type functor. -- -- Like Identity, but with a shorter name. newtype I a I :: a -> I a -- | The constant type functor. -- -- Like Constant, but kind-polymorphic in its second argument and -- with a shorter name. newtype K a (b :: k) K :: a -> K a (b :: k) -- | Extract the contents of an I value. unI :: I a -> a -- | Lifted functions. newtype ( (f :: k -> Type) -.-> (g :: k -> Type) ) (a :: k) Fn :: (f a -> g a) -> (-.->) (f :: k -> Type) (g :: k -> Type) (a :: k) [apFn] :: (-.->) (f :: k -> Type) (g :: k -> Type) (a :: k) -> f a -> g a infixr 1 -.-> -- | Composition of constraints. -- -- Note that the result of the composition must be a constraint, and -- therefore, in Compose f g, the kind of f is -- k -> Constraint. The kind of g, however, -- is l -> k and can thus be a normal type constructor. -- -- A typical use case is in connection with All on an NP or -- an NS. For example, in order to denote that all elements on an -- NP f xs satisfy Show, we can say All -- (Compose Show f) xs. class f g x => Compose (f :: k -> Constraint) (g :: k1 -> k) (x :: k1) infixr 9 `Compose` -- | An explicit dictionary carrying evidence of a class constraint. -- -- The constraint parameter is separated into a second argument so that -- Dict c is of the correct kind to be used directly as a -- parameter to e.g. NP. data Dict (c :: k -> Constraint) (a :: k) [Dict] :: forall {k} (c :: k -> Constraint) (a :: k). c a => Dict c a -- | Constraint representing the fact that the field x can be get -- and set on the record type r and has field type a. -- This constraint will be solved automatically, but manual instances may -- be provided as well. -- -- The function should satisfy the invariant: -- --
--   uncurry ($) (hasField @x r) == r
--   
class HasField (x :: k) r a | x r -> a -- | Function to get and set a field in a record. hasField :: HasField x r a => r -> (a -> r, a) -- | This class gives the string associated with a type-level symbol. There -- are instances of the class for every concrete literal: "hello", etc. class KnownSymbol (n :: Symbol) -- | Advanced interface (with a functor argument) -- -- See Data.Record.Anon.Simple for the simple interface. You will -- probably also want to import Data.Record.Anon. -- -- Intended for qualified import. -- --
--   import Data.Record.Anon
--   import Data.Record.Anon.Advanced (Record)
--   import qualified Data.Record.Anon.Advanced as Anon
--   
module Data.Record.Anon.Advanced -- | Anonymous record data Record (f :: k -> Type) (r :: Row k) -- | Empty record empty :: Record f '[] -- | Insert new field -- --
--   >>> :{
--   example :: Record Maybe [ "a" := Bool, "b" := Int ]
--   example =
--        insert #a (Just True)
--      $ insert #b Nothing
--      $ empty
--   :}
--   
-- -- Instead of using insert and empty, you can also write -- this as -- --
--   example = ANON_F {
--         a = Just True
--       , b = Nothing
--       }
--   
insert :: Field n -> f a -> Record f r -> Record f ((n := a) : r) -- | Applicative insert -- -- This is a simple wrapper around insert, but can be quite useful -- when constructing records. Consider code like -- --
--   >>> :{
--   example :: Applicative m => m a -> m b -> m (a, b)
--   example ma mb = (,) <$> ma <*> mb
--   :}
--   
-- -- We cannot really extend this to the world of named records, but we -- can do something comparable using anonymous records: -- --
--   >>> :{
--   example ::
--        Applicative m
--     => m (f a) -> m (f b) -> m (Record f [ "a" := a, "b" := b ])
--   example ma mb =
--         insertA #a ma
--       $ insertA #b mb
--       $ Prelude.pure empty
--   :}
--   
-- -- As for regular insert, this example too can instead be written -- using ANON_F and sequenceA (or sequenceA'). -- --
--   example ma mb = sequenceA $ ANON_F {
--         a = Comp ma
--       , b = Comp mb
--       }
--   
insertA :: Applicative m => Field n -> m (f a) -> m (Record f r) -> m (Record f ((n := a) : r)) -- | Apply all pending changes to the record -- -- Updates to a record are stored in a hashtable. As this hashtable -- grows, record field access and update will become more expensive. -- Applying the updates, resulting in a flat vector, is an O(n) -- operation. This will happen automatically whenever another -- O(n) operation is applied (for example, mapping a function -- over the record). However, occassionally it is useful to explicitly -- apply these changes, for example after constructing a record or -- updating a lot of fields. applyPending :: Record f r -> Record f r -- | Get field from the record -- -- This is just a wrapper around getField. -- --
--   >>> :{
--   example :: Record Maybe [ "a" := Bool, "b" := Int ] -> Maybe Bool
--   example r = get #a r
--   :}
--   
-- -- If using record-dot-preprocessor, you can also write this -- example as -- --
--   example r = r.a
--   
-- -- If the field does not exist, you will get a type error about an -- unsolvable RowHasField constraint: -- --
--   >>> :{
--   absentField :: Record Maybe [ "a" := Bool, "b" := Int ] -> Maybe Char
--   absentField r = get #c r
--   :}
--   ...
--   ...No instance for (RowHasField "c"...
--   ...
--   
-- -- Type mismatches will result in regular type errors: -- --
--   >>> :{
--   wrongType :: Record Maybe [ "a" := Bool, "b" := Int ] -> Maybe Char
--   wrongType r = get #a r
--   :}
--   ...
--   ...Couldn't match...Char...Bool...
--   ...
--   
-- -- When part of the record is not known, it might not be possible to -- resolve a HasField constraint until later. For example, in -- --
--   >>> :{
--   unknownField :: Record Maybe [ x := Bool, "b" := Int ] -> Maybe Int
--   unknownField r = get #b r
--   :}
--   ...
--   ...No instance for (RowHasField "b"...
--   ...
--   
-- -- (Note that x here is a variable, not a string.) It is -- important that the constraint remains unsolved in this example, -- because if x == "b", the first field would shadow the second, -- and the result type should be Maybe Bool instead of Maybe -- Int. get :: RowHasField n r a => Field n -> Record f r -> f a -- | Update field in the record -- -- This is just a wrapper around setField. -- --
--   >>> :{
--   example ::
--        Record Maybe [ "a" := Bool, "b" := Int ]
--     -> Record Maybe [ "a" := Bool, "b" := Int ]
--   example r = set #a (Just False) r
--   :}
--   
-- -- If using record-dot-preprocessor, can also write this example -- as -- --
--   example r = r{a = Just False}
--   
set :: RowHasField n r a => Field n -> f a -> Record f r -> Record f r -- | Project from one record to another -- -- Both the source record and the target record must be fully known. -- -- The target record can omit fields from the source record, as well as -- rearrange them: -- --
--   >>> :{
--   example ::
--        Record f [ "a" := Char, "b" := Int, "c" := Bool ]
--     -> Record f [ "c" := Bool, "a" := Char ]
--   example = project
--   :}
--   
-- -- Of course, it is not possible to add fields: -- --
--   >>> :{
--   example ::
--        Record f [ "c" := Bool, "a" := Char ]
--     -> Record f [ "a" := Char, "b" := Int, "c" := Bool ]
--   example = project
--   :}
--   ...
--   ...No instance for (SubRow...
--   ...
--   
-- -- Type inference will work through projections: field types are unified -- based on their name: -- --
--   >>> :{
--   example ::
--        Record f [ "a" := Char, "b" := Int, "c" := Bool ]
--     -> Record f [ "c" := _, "a" := Char ]
--   example = project
--   :}
--   ...
--   ...Found type wildcard...Bool...
--   ...
--   
-- -- As we saw in merge, project can also flatten -- Merged rows. project :: SubRow r r' => Record f r -> Record f r' -- | Inject smaller record into larger record -- -- This is just the lens setter. inject :: SubRow r r' => Record f r' -> Record f r -> Record f r -- | Lens from one record to another -- -- See project for examples (project is just the lens -- getter, without the setter). lens :: SubRow r r' => Record f r -> (Record f r', Record f r' -> Record f r) -- | Merge two records -- -- The Merge type family does not reduce: -- --
--   >>> :{
--   example :: Record Maybe (Merge '[ "a" :=  Bool ] '[])
--   example = merge (insert #a (Just True) empty) empty
--   :}
--   
-- -- If you want to flatten the row after merging, you can use -- project: -- --
--   >>> :{
--   example :: Record Maybe '[ "a" :=  Bool ]
--   example = project $ merge (insert #a (Just True) empty) empty
--   :}
--   
-- -- HasField constraints can be resolved for merged records, -- subject to the same condition discussed in get: all fields in -- the record must be known up to the requested field (in case of -- shadowing). So the record may be fully known: -- --
--   >>> :{
--   example :: Record f (Merge '[ "a" := Bool ] '[ "b" := Char ]) -> f Char
--   example r = get #b r
--   :}
--   
-- -- but it doesn't have to be: -- --
--   >>> :{
--   example :: Record I (Merge '[ "a" := Bool ] r) -> I Bool
--   example = get #a
--   :}
--   
-- -- However, just like in the case of unknown fields (see example in -- get), if earlier parts in the record are unknown we get type -- error: -- --
--   >>> :{
--   example :: Record I (Merge r '[ "b" := Char ]) -> I Char
--   example r = get #b r
--   :}
--   ...
--   ...No instance for (RowHasField "b"...
--   ...
--   
merge :: Record f r -> Record f r' -> Record f (Merge r r') -- | Analogue to fmap map :: (forall x. f x -> g x) -> Record f r -> Record g r -- | Constrained form of map cmap :: AllFields r c => Proxy c -> (forall x. c x => f x -> g x) -> Record f r -> Record g r -- | Analogue of pure pure :: KnownFields r => (forall x. f x) -> Record f r -- | Constrained form of pure cpure :: AllFields r c => Proxy c -> (forall x. c x => f x) -> Record f r -- | Analogue of <*> ap :: Record (f -.-> g) r -> Record f r -> Record g r -- | Analogue of toList collapse :: Record (K a) r -> [a] -- | Like collapse, but also include field names toList :: KnownFields r => Record (K a) r -> [(String, a)] -- | Analogue to mapM mapM :: Applicative m => (forall x. f x -> m (g x)) -> Record f r -> m (Record g r) -- | Constrained form of cmap cmapM :: (Applicative m, AllFields r c) => Proxy c -> (forall x. c x => f x -> m (g x)) -> Record f r -> m (Record g r) -- | Analogue of sequenceA sequenceA :: Applicative m => Record (m :.: f) r -> m (Record f r) -- | Simplified form of sequenceA sequenceA' :: Applicative m => Record m r -> m (Record I r) -- | Analogue of zip zip :: Record f r -> Record g r -> Record (Product f g) r -- | Analogue of zipWith zipWith :: (forall x. f x -> g x -> h x) -> Record f r -> Record g r -> Record h r -- | Analogue of zipWithM zipWithM :: Applicative m => (forall x. f x -> g x -> m (h x)) -> Record f r -> Record g r -> m (Record h r) -- | Constrained form of zipWith czipWith :: AllFields r c => Proxy c -> (forall x. c x => f x -> g x -> h x) -> Record f r -> Record g r -> Record h r -- | Constrained form of zipWithM czipWithM :: (Applicative m, AllFields r c) => Proxy c -> (forall x. c x => f x -> g x -> m (h x)) -> Record f r -> Record g r -> m (Record h r) -- | Record of dictionaries -- -- This reifies an AllFields constraint as a record. -- -- Inverse to reflectKnownFields. reifyAllFields :: AllFields r c => proxy c -> Record (Dict c) r -- | Establish AllFields from a record of dictionaries -- -- Inverse to reifyKnownFields. reflectAllFields :: Record (Dict c) r -> Reflected (AllFields r c) -- | Record of field names -- -- This reifies a KnownFields constraint as a record. -- -- Inverse to reflectAllFields. reifyKnownFields :: KnownFields r => proxy r -> Record (K String) r -- | Establish KnownFields from a record of field names -- -- Inverse to reifyAllFields. reflectKnownFields :: Record (K String) r -> Reflected (KnownFields r) -- | InRow r a is evidence that there exists some n s.t. -- (n := a) in r. data InRow (r :: Row k) (a :: k) [InRow] :: forall k (n :: Symbol) (r :: Row k) (a :: k). (KnownSymbol n, RowHasField n r a) => Proxy n -> InRow r a -- | Record over r' with evidence that every field is in -- r. -- -- This reifies a SubRow constraint. -- -- Inverse to reflectSubRow. reifySubRow :: (KnownFields r', SubRow r r') => Record (InRow r) r' -- | Establish SubRow from a record of evidence. -- -- Inverse to reifySubRow. reflectSubRow :: Record (InRow r) r' -> Reflected (SubRow r r') -- | Discovered row variable -- -- See someRecord for detailed discussion. data SomeRecord (f :: k -> Type) [SomeRecord] :: forall k (r :: Row k) (f :: k -> Type). KnownFields r => Record (Product (InRow r) f) r -> SomeRecord f -- | Construct record with existentially quantified row variable -- -- Existentially quantified records arise for example when parsing JSON -- values as records. Pattern matching on the result of someRecord -- brings into scope an existentially quantified row variable r, -- along with a record over r; every field in record contains -- the value specified, as well as evidence that that that field is -- indeed an element of r. -- -- For such a record to be useful, you will probably want to prove -- additional constraints AllFields r c; you can do this using -- reflectAllFields, provided that you carefully pick your -- f such that you can define a function -- --
--   fieldSatisfiesC :: forall c. f x -> Dict c x
--   
-- -- for every c you want to prove. -- -- It is also possible to do a runtime check to see if the existential -- row r can be projected to some concrete known row -- r'. To do this, construct a record of evidence with type -- --
--   Record (InRow r) r'
--   
-- -- and then call reflectSubRow. To construct this record of -- evidence you will need to do a runtime type check to verify that the -- types of the fields in concrete row match the types of the -- corresponding fields in the inferred row (the inferred row may contain -- fields that are not present in the concrete row, of course). An -- obvious candidate for doing this is Typeable, but for specific -- applications (with specific subsets of types of interest) other -- choices may be possible also. -- -- The large-anon test suite contains examples of doing both of -- these things; see Test.Infra.DynRecord.Simple (or -- Test.Infra.DynRecord.Advanced for rows over kind other than -- Type) for examples of proving additional constraints, and -- Test.Infra.Discovery for an example of how you could do a -- projection check. someRecord :: [(String, Some f)] -> SomeRecord f -- | Introduce type variable for a row -- -- This can be used in conjunction with letInsertAs: -- --
--   >>> :{
--   example :: Record I '[ "a" := Int, "b" := Char, "c" := Bool ]
--   example = letRecordT $ \p -> castEqual $
--       letInsertAs p #c (I True) empty $ \xs02 ->
--       letInsertAs p #b (I 'X' ) xs02  $ \xs01 ->
--       letInsertAs p #a (I 1   ) xs01  $ \xs00 ->
--       castEqual xs00
--   :}
--   
letRecordT :: forall r f. (forall r'. Let r' r => Proxy r' -> Record f r) -> Record f r -- | Insert field into a record and introduce type variable for the result letInsertAs :: forall r r' f n a. Proxy r -> Field n -> f a -> Record f r' -> (forall r''. Let r'' ((n := a) : r') => Record f r'' -> Record f r) -> Record f r castEqual :: Equal a b => a -> b -- | Simple interface (without a functor argument) -- -- See Data.Record.Anon.Advanced for the advanced interface. You -- will probably also want to import Data.Record.Anon. -- -- Intended for qualified import. -- --
--   import Data.Record.Anon
--   import Data.Record.Anon.Simple (Record)
--   import qualified Data.Record.Anon.Simple as Anon
--   
module Data.Record.Anon.Simple -- | Anonymous record -- -- A Record r has a field n of type x for -- every (n := x) in r. -- -- To construct a Record, use insert and empty, or -- use the ANON syntax. See insert for examples. -- -- To access fields of the record, either use the HasField -- instances (possibly using the record-dot-preprocessor), or -- using get and set. -- -- Remember to enable the plugin when working with anonymous records: -- --
--   {-# OPTIONS_GHC -fplugin=Data.Record.Anon.Plugin #-}
--   
-- -- NOTE: For some applications it is useful to have an additional functor -- parameter f, so that every field has type f x -- instead. See Data.Record.Anon.Advanced. data Record r -- | Empty record empty :: Record '[] -- | Insert new field -- --
--   >>> :{
--   example :: Record [ "a" := Bool, "b" := Int ]
--   example =
--        insert #a True
--      $ insert #b 1
--      $ empty
--   :}
--   
-- -- Instead of using insert and empty, you can also write -- this as -- --
--   example = ANON {
--         a = True
--       , b = 1
--       }
--   
insert :: Field n -> a -> Record r -> Record ((n := a) : r) -- | Applicative insert -- -- This is a simple wrapper around insert, but can be quite useful -- when constructing records. Consider code like -- --
--   >>> :{
--   example :: Applicative m => m a -> m b -> m (a, b)
--   example ma mb = (,) <$> ma <*> mb
--   :}
--   
-- -- We cannot really extend this to the world of named records, but we -- can do something comparable using anonymous records: -- --
--   >>> :{
--   example :: Applicative m => m a -> m b -> m (Record [ "a" := a, "b" := b ])
--   example ma mb =
--         insertA #a ma
--       $ insertA #b mb
--       $ pure empty
--   :}
--   
-- -- However, it may be more convenient to use the advanced API for this. -- See insertA. insertA :: Applicative m => Field n -> m a -> m (Record r) -> m (Record ((n := a) : r)) -- | Apply all pending changes to the record -- -- Updates to a record are stored in a hashtable. As this hashtable -- grows, record field access and update will become more expensive. -- Applying the updates, resulting in a flat vector, is an O(n) -- operation. This will happen automatically whenever another -- O(n) operation is applied (for example, mapping a function -- over the record). However, occassionally it is useful to explicitly -- apply these changes, for example after constructing a record or -- updating a lot of fields. applyPending :: Record r -> Record r -- | Get field from the record -- -- This is just a wrapper around getField. -- --
--   >>> :{
--   example :: Record [ "a" := Bool, "b" := Int ] -> Bool
--   example r = get #a r
--   :}
--   
-- -- If using record-dot-preprocessor, you can also write this -- example as -- --
--   example r = r.a
--   
-- -- See get for additional discussion. get :: RowHasField n r a => Field n -> Record r -> a -- | Update field in the record -- -- This is just a wrapper around setField. -- --
--   >>> :{
--   example ::
--        Record [ "a" := Bool, "b" := Int ]
--     -> Record [ "a" := Bool, "b" := Int ]
--   example r = set #a False r
--   :}
--   
-- -- If using record-dot-preprocessor, can also write this example -- as -- --
--   example r = r{a = False}
--   
set :: RowHasField n r a => Field n -> a -> Record r -> Record r -- | Project from one record to another -- -- Both the source record and the target record must be fully known. -- -- The target record can omit fields from the source record, as well as -- rearrange them: -- --
--   >>> :{
--   example ::
--        Record [ "a" := Char, "b" := Int, "c" := Bool ]
--     -> Record [ "c" := Bool, "a" := Char ]
--   example = project
--   :}
--   
-- -- As we saw in merge, project can also flatten -- Merged rows. See project for additional discussion. project :: SubRow r r' => Record r -> Record r' -- | Inject smaller record into larger record -- -- This is just the lens setter. inject :: SubRow r r' => Record r' -> Record r -> Record r -- | Lens from one record to another -- -- See project for examples (project is just the lens -- getter, without the setter). lens :: SubRow r r' => Record r -> (Record r', Record r' -> Record r) -- | Merge two records -- -- The Merge type family does not reduce: -- --
--   >>> :{
--   example :: Record (Merge '[ "a" :=  Bool ] '[])
--   example = merge (insert #a True empty) empty
--   :}
--   
-- -- If you want to flatten the row after merging, you can use -- project: -- --
--   >>> :{
--   example :: Record '[ "a" :=  Bool ]
--   example = project $ merge (insert #a True empty) empty
--   :}
--   
-- -- See merge for additional discussion. merge :: Record r -> Record r' -> Record (Merge r r') -- | Move from the simple to the advanced interface -- -- This is an O(1) operation. toAdvanced :: Record r -> Record I r -- | Move from the advanced to the simple interface -- -- This is an O(1) operation. fromAdvanced :: Record I r -> Record r -- | Sequence all actions sequenceA :: Applicative m => Record m r -> m (Record r) -- | Introduce type variable for a row -- -- This can be used in conjunction with letInsertAs: -- --
--   >>> :{
--   example :: Record '[ "a" := Int, "b" := Char, "c" := Bool ]
--   example = letRecordT $ \p -> castEqual $
--       letInsertAs p #c True empty $ \xs02 ->
--       letInsertAs p #b 'X'  xs02  $ \xs01 ->
--       letInsertAs p #a 1    xs01  $ \xs00 ->
--       castEqual xs00
--   :}
--   
letRecordT :: forall r. (forall r'. Let r' r => Proxy r' -> Record r) -> Record r -- | Insert field into a record and introduce type variable for the result letInsertAs :: forall r r' n a. Proxy r -> Field n -> a -> Record r' -> (forall r''. Let r'' ((n := a) : r') => Record r'' -> Record r) -> Record r castEqual :: Equal a b => a -> b