-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Generic programming API for large-records and large-anon -- -- The large-generics package offers a style of generic programming -- inspired by generics-sop, but optimized for compilation time. For more -- information, see the blog posts "Avoiding quadratic core code size -- with large records" -- https://well-typed.com/blog/2021/08/large-records/. @package large-generics @version 0.2.2 -- | Definition of Rep and functions that do not depend on -- ".Generic" -- -- Defined as a separate module to avoid circular module dependencies. module Data.Record.Generic.Rep.Internal -- | Representation of some record a -- -- The f parameter describes which functor has been applied to -- all fields of the record; in other words Rep I is isomorphic -- to the record itself. newtype Rep f a Rep :: SmallArray (f Any) -> Rep f a -- | Strict map -- -- map' f x is strict in x: if x is undefined, -- map f x will also be undefined, even if f never -- needs any values from x. map' :: (forall x. f x -> g x) -> Rep f a -> Rep g a sequenceA :: Applicative m => Rep (m :.: f) a -> m (Rep f a) -- | Convert list to Rep -- -- Does not check that the list has the right number of elements. unsafeFromList :: [b] -> Rep (K b) a -- | Convert list to Rep -- -- Does not check that the list has the right number of elements, nor the -- types of those elements. unsafeFromListAny :: [f Any] -> Rep f a collapse :: Rep (K a) b -> [a] -- | Convert Rep to list toListAny :: Rep f a -> [f Any] -- | Avoid potential segfault with ghc < 9.0 -- -- See https://gitlab.haskell.org/ghc/ghc/-/issues/16893. I -- haven't actually seen this fail in large-records, but we saw it fail -- in the compact representation branch of sop-core, and what we do here -- is not so different, so better to play it safe. noInlineUnsafeCo :: forall a b. a -> b instance GHC.Show.Show x => GHC.Show.Show (Data.Record.Generic.Rep.Internal.Rep (Data.SOP.BasicFunctors.K x) a) instance GHC.Classes.Eq x => GHC.Classes.Eq (Data.Record.Generic.Rep.Internal.Rep (Data.SOP.BasicFunctors.K x) a) module Data.Record.Generic class Generic a where { -- | Constraints a c means "all fields of a satisfy -- c" type Constraints a :: (Type -> Constraint) -> Constraint; -- | Type-level metadata -- -- NOTE: using type-level lists without resulting in quadratic core code -- is extremely difficult. Any use of this type-level metadata therefore -- needs delibrate consideration. Some examples: -- -- o Within the large-generics library, MetadataOf is -- used in the definition of HasNormalForm. This constraint is -- carefully defined to avoid quadratic code, as described in the -- presentation "Avoiding Quadratic Blow-up During Compilation" -- https://skillsmatter.com/skillscasts/17262-avoiding-quadratic-blow-up-during-compilation -- o The large-records library uses it to provide a -- compatibility layer between it and sop-core; this is however -- only for testing purposes, and the quadratic code here is simply -- accepted. type MetadataOf a :: [(Symbol, Type)]; } -- | Translate to generic representation from :: Generic a => a -> Rep I a -- | Translate from generic representation to :: Generic a => Rep I a -> a -- | Construct vector of dictionaries, one for each field of the record dict :: (Generic a, Constraints a c) => Proxy c -> Rep (Dict c) a -- | Metadata metadata :: Generic a => proxy a -> Metadata a -- | Representation of some record a -- -- The f parameter describes which functor has been applied to -- all fields of the record; in other words Rep I is isomorphic -- to the record itself. newtype Rep f a Rep :: SmallArray (f Any) -> Rep f a data Metadata a Metadata :: String -> String -> Int -> Rep FieldMetadata a -> Metadata a [recordName] :: Metadata a -> String [recordConstructor] :: Metadata a -> String [recordSize] :: Metadata a -> Int [recordFieldMetadata] :: Metadata a -> Rep FieldMetadata a data FieldStrictness FieldStrict :: FieldStrictness FieldLazy :: FieldStrictness recordFieldNames :: Metadata a -> Rep (K String) a data FieldMetadata x [FieldMetadata] :: KnownSymbol name => Proxy name -> FieldStrictness -> FieldMetadata x type family FieldName (field :: (Symbol, Type)) :: Symbol type family FieldType (field :: (Symbol, Type)) :: Type class (field ~ '(FieldName field, FieldType field), KnownSymbol (FieldName field)) => IsField field -- | 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) -- | 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 -.-> -- | 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 -- | Extract the contents of a K value. unK :: forall {k} a (b :: k). K a b -> a -- | Extract the contents of an I value. unI :: I a -> a -- | Extract the contents of a Comp value. unComp :: forall {l} {k} f (g :: k -> l) (p :: k). (f :.: g) p -> f (g p) -- | Lift the given function. mapII :: (a -> b) -> I a -> I b -- | Lift the given function. mapIK :: forall {k} a b (c :: k). (a -> b) -> I a -> K b c -- | Lift the given function. mapKI :: forall {k} a b (c :: k). (a -> b) -> K a c -> I b -- | Lift the given function. mapKK :: forall {k1} {k2} a b (c :: k1) (d :: k2). (a -> b) -> K a c -> K b d -- | Lift the given function. mapIII :: (a -> b -> c) -> I a -> I b -> I c -- | Lift the given function. mapIIK :: forall {k} a b c (d :: k). (a -> b -> c) -> I a -> I b -> K c d -- | Lift the given function. mapIKI :: forall {k} a b c (d :: k). (a -> b -> c) -> I a -> K b d -> I c -- | Lift the given function. mapIKK :: forall {k1} {k2} a b c (d :: k1) (e :: k2). (a -> b -> c) -> I a -> K b d -> K c e -- | Lift the given function. mapKII :: forall {k} a b c (d :: k). (a -> b -> c) -> K a d -> I b -> I c -- | Lift the given function. mapKIK :: forall {k1} {k2} a b c (d :: k1) (e :: k2). (a -> b -> c) -> K a d -> I b -> K c e -- | Lift the given function. mapKKI :: forall {k1} {k2} a b c (d :: k1) (e :: k2). (a -> b -> c) -> K a d -> K b e -> I c -- | Lift the given function. mapKKK :: forall {k1} {k2} {k3} a b c (d :: k1) (e :: k2) (f :: k3). (a -> b -> c) -> K a d -> K b e -> K c f -- | 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) instance (field GHC.Types.~ '(Data.Record.Generic.FieldName field, Data.Record.Generic.FieldType field), GHC.TypeLits.KnownSymbol (Data.Record.Generic.FieldName field)) => Data.Record.Generic.IsField field -- | Operations on the generic representation -- -- We also re-export some non-derive functions to clarify where they -- belong in this list. -- -- This module is intended for qualified import. -- --
-- import qualified Data.Record.Generic.Rep as Rep ---- -- TODO: Could we provide instances for the generics-sop type -- classes? Might lessen the pain of switching between the two or using -- both? module Data.Record.Generic.Rep -- | Representation of some record a -- -- The f parameter describes which functor has been applied to -- all fields of the record; in other words Rep I is isomorphic -- to the record itself. newtype Rep f a Rep :: SmallArray (f Any) -> Rep f a map :: Generic a => (forall x. f x -> g x) -> Rep f a -> Rep g a mapM :: (Applicative m, Generic a) => (forall x. f x -> m (g x)) -> Rep f a -> m (Rep g a) cmap :: (Generic a, Constraints a c) => Proxy c -> (forall x. c x => f x -> g x) -> Rep f a -> Rep g a cmapM :: forall m f g c a. (Generic a, Applicative m, Constraints a c) => Proxy c -> (forall x. c x => f x -> m (g x)) -> Rep f a -> m (Rep g a) zip :: Generic a => Rep f a -> Rep g a -> Rep (Product f g) a zipWith :: Generic a => (forall x. f x -> g x -> h x) -> Rep f a -> Rep g a -> Rep h a zipWithM :: forall m f g h a. (Generic a, Applicative m) => (forall x. f x -> g x -> m (h x)) -> Rep f a -> Rep g a -> m (Rep h a) czipWith :: (Generic a, Constraints a c) => Proxy c -> (forall x. c x => f x -> g x -> h x) -> Rep f a -> Rep g a -> Rep h a czipWithM :: forall m f g h c a. (Generic a, Applicative m, Constraints a c) => Proxy c -> (forall x. c x => f x -> g x -> m (h x)) -> Rep f a -> Rep g a -> m (Rep h a) collapse :: Rep (K a) b -> [a] sequenceA :: Applicative m => Rep (m :.: f) a -> m (Rep f a) pure :: forall f a. Generic a => (forall x. f x) -> Rep f a cpure :: (Generic a, Constraints a c) => Proxy c -> (forall x. c x => f x) -> Rep f a -- | Higher-order version of * -- -- Lazy in the second argument. ap :: forall f g a. Generic a => Rep (f -.-> g) a -> Rep f a -> Rep g a data Index a x indexToInt :: Index a x -> Int getAtIndex :: Index a x -> Rep f a -> f x putAtIndex :: Index a x -> f x -> Rep f a -> Rep f a updateAtIndex :: Functor m => Index a x -> (f x -> m (f x)) -> Rep f a -> m (Rep f a) allIndices :: forall a. Generic a => Rep (Index a) a -- | Map with index -- -- This is an important building block in this module. Crucially, -- mapWithIndex f a is lazy in a, reading elements from -- a only if and when f demands them. mapWithIndex :: forall f g a. Generic a => (forall x. Index a x -> f x -> g x) -> Rep f a -> Rep g a module Data.Record.Generic.NFData -- | Generic rnf function -- -- Typical usage: -- --
-- instance NFData T where -- rnf = grnf --grnf :: (Generic a, Constraints a NFData) => a -> () -- | Simple example of a generic function module Data.Record.Generic.LowerBound -- | Types with a lower bound class LowerBound a lowerBound :: LowerBound a => a glowerBound :: (Generic a, Constraints a LowerBound) => a instance Data.Record.Generic.LowerBound.LowerBound GHC.Types.Word instance Data.Record.Generic.LowerBound.LowerBound GHC.Types.Bool instance Data.Record.Generic.LowerBound.LowerBound GHC.Types.Char instance Data.Record.Generic.LowerBound.LowerBound () instance Data.Record.Generic.LowerBound.LowerBound [a] -- | Generic conversion to/from JSON module Data.Record.Generic.JSON gtoJSON :: forall a. (Generic a, Constraints a ToJSON) => a -> Value gparseJSON :: forall a. (Generic a, Constraints a FromJSON) => Value -> Parser a -- | Interop with standard GHC generics module Data.Record.Generic.GHC -- | Route from GHC generics to LR generics -- -- Suppose a function such as -- --
-- allEqualTo :: Eq a => a -> [a] -> Bool -- allEqualTo x = all (== x) ---- -- is instead written as -- --
-- allEqualTo :: (GHC.Generic a, GHC.GEq' (GHC.Rep a)) => a -> [a] -> Bool -- allEqualTo x = all (GHC.geqdefault x) ---- -- where instead of using an indirection through an auxiliary type class -- Eq, it directly assumes GHC.Generics and uses a -- concrete generic implementation. Such design is arguably questionable, -- but for example beam-core contains many such deeply ingrained -- assumptions of the availability of GHC.Generics. -- -- In order to be able to call such a function on a large record -- Foo, largeRecord will generate an instance -- --
-- instance GHC.Generic Foo where -- type Rep Foo = ThroughLRGenerics Foo -- -- from = WrapThroughLRGenerics -- to = unwrapThroughLRGenerics ---- -- For our running example, this instance makes it possible to call -- allEqualTo provided we then provide an instance -- --
-- instance ( LR.Generic a -- , LR.Constraints a Eq -- ) => GHC.GEq' (ThroughLRGenerics a) where -- geq' = LR.geq `on` unwrapThroughLRGenerics ---- -- Effectively, ThroughLRGenerics can be used to redirect a -- function that uses GHC generics to a function that uses LR generics. newtype ThroughLRGenerics a p WrapThroughLRGenerics :: a -> ThroughLRGenerics a p [unwrapThroughLRGenerics] :: ThroughLRGenerics a p -> a -- | GHC generics metadata -- -- TODO: Currently we provide metadata only for the record fields, not -- the constructor or type name data GhcMetadata a GhcMetadata :: Rep GhcFieldMetadata a -> GhcMetadata a [ghcMetadataFields] :: GhcMetadata a -> Rep GhcFieldMetadata a data GhcFieldMetadata :: Type -> Type [GhcFieldMetadata] :: forall (f :: Meta) (a :: Type). Selector f => Proxy f -> GhcFieldMetadata a ghcMetadata :: Generic a => proxy a -> GhcMetadata a module Data.Record.Generic.Eq -- | Generic equality function -- -- Typical usage: -- --
-- instance Eq T where -- (==) = geq ---- -- TODO: Should we worry about short-circuiting here? geq :: (Generic a, Constraints a Eq) => a -> a -> Bool gcompare :: (Generic a, Constraints a Ord) => a -> a -> Ordering -- | Interop with generics-sop generics module Data.Record.Generic.SOP newtype Field (f :: Type -> Type) (field :: (Symbol, Type)) [Field] :: f (FieldType field) -> Field f field fromSOP :: SListI (MetadataOf a) => NP (Field f) (MetadataOf a) -> Rep f a toSOP :: SListI (MetadataOf a) => Rep f a -> Maybe (NP (Field f) (MetadataOf a)) -- | Translate constraints -- -- When using toSOP, if you start with something of type -- --
-- Rep f a ---- -- you end up with something of type -- --
-- NP (Field f) (MetadataOf a) ---- -- When doing so, toDictAll can translate -- --
-- Constraints a (Compose c f) ---- -- (which is useful over the original representation) to -- --
-- All (Compose c (Field f)) (MetadataOf a) ---- -- which is useful for the translated representation. toDictAll :: forall f a c. (Generic a, Constraints a (Compose c f), All IsField (MetadataOf a), forall nm x. c (f x) => c (Field f '(nm, x))) => Proxy f -> Proxy a -> Proxy c -> Dict (All (Compose c (Field f))) (MetadataOf a) glowerBound :: (Generic a, All LowerBound xs, Code a ~ '[xs]) => a instance GHC.Show.Show (f x) => GHC.Show.Show (Data.Record.Generic.SOP.Field f '(nm, x)) instance GHC.Classes.Eq (f x) => GHC.Classes.Eq (Data.Record.Generic.SOP.Field f '(nm, x)) module Data.Record.Generic.Show -- | Generic definition of showsPrec, compatible with the GHC -- generated one. -- -- Typical usage: -- --
-- instance Show T where -- showsPrec = gshowsPrec --gshowsPrec :: forall a. (Generic a, Constraints a Show) => Int -> a -> ShowS module Data.Record.Generic.Transform type family Interpreted (d :: dom) (x :: Type) :: Type newtype Interpret d x Interpret :: Interpreted d x -> Interpret d x liftInterpreted :: (Interpreted dx x -> Interpreted dy y) -> Interpret dx x -> Interpret dy y liftInterpretedA2 :: Applicative m => (Interpreted dx x -> Interpreted dy y -> m (Interpreted dz z)) -> Interpret dx x -> Interpret dy y -> m (Interpret dz z) type HasNormalForm d x y = InterpretTo d (MetadataOf x) (MetadataOf y) type family InterpretTo d xs ys :: Constraint type family IfEqual x y (r :: k) :: k -- | Construct normal form -- -- TODO: Documentation. normalize :: HasNormalForm d x y => Proxy d -> Proxy y -> Rep I x -> Rep (Interpret d) y denormalize :: HasNormalForm d x y => Proxy d -> Proxy y -> Rep (Interpret d) y -> Rep I x data Uninterpreted x data DefaultInterpretation (f :: Type -> Type) normalize1 :: forall d f x. HasNormalForm (d f) (x f) (x Uninterpreted) => Proxy d -> Rep I (x f) -> Rep (Interpret (d f)) (x Uninterpreted) denormalize1 :: forall d f x. HasNormalForm (d f) (x f) (x Uninterpreted) => Proxy d -> Rep (Interpret (d f)) (x Uninterpreted) -> Rep I (x f) class StandardInterpretation d f standardInterpretation :: StandardInterpretation d f => Proxy d -> (Interpreted (d f) (Uninterpreted x) -> f x, f x -> Interpreted (d f) (Uninterpreted x)) standardInterpretation :: (StandardInterpretation d f, Coercible (Interpreted (d f) (Uninterpreted x)) (f x)) => Proxy d -> (Interpreted (d f) (Uninterpreted x) -> f x, f x -> Interpreted (d f) (Uninterpreted x)) toStandardInterpretation :: forall d f x. StandardInterpretation d f => Proxy d -> f x -> Interpret (d f) (Uninterpreted x) fromStandardInterpretation :: forall d f x. StandardInterpretation d f => Proxy d -> Interpret (d f) (Uninterpreted x) -> f x instance Data.Record.Generic.Transform.StandardInterpretation Data.Record.Generic.Transform.DefaultInterpretation f -- | van Laarhoven lenses for large records. The type synonym -- --
-- type Lens' s a = forall f. Functor f => (a -> f a) -> s -> f s ---- -- Appears below, however it is not exported to avoid conflicts with -- other libraries defining equivalent synonyms. module Data.Record.Generic.Lens.VL data SimpleRecordLens a b [SimpleRecordLens] :: Lens' a b -> SimpleRecordLens a b -- | Lens for higher-kinded record -- -- See lensesForHKRecord for details. data HKRecordLens d (f :: Type -> Type) tbl x [HKRecordLens] :: Lens' (tbl f) (Interpret (d f) x) -> HKRecordLens d f tbl x -- | Lens into a regular record -- -- See lensesForRegularRecord data RegularRecordLens tbl f x [RegularRecordLens] :: Lens' (tbl f) (f x) -> RegularRecordLens tbl f x -- | Construct lenses for each field in the record -- -- NOTE: This is of limited use since we cannot pattern match on the -- resulting Rep in any meaningful way. It is possible to go -- through the SOP adapter, but if we do, we incur quadratic cost again. -- -- We can do better for higher-kinded records, and better still for -- regular higher-kinded records. See lensesForHKRecord and -- lensesForRegularRecord. lensesForSimpleRecord :: forall a. Generic a => Rep (SimpleRecordLens a) a -- | Lenses for higher-kinded records -- -- NOTE: The lenses constructed by this function are primarily intended -- for further processing, either by lensesForRegularRecord or -- using application specific logic. Details below. -- -- Suppose we have a record tbl f which is indexed by a functor -- f, and we want to construct lenses from tbl f to -- each field in the record. Using the Transform infrastructure, -- we can construct a lens -- --
-- tbl f ~~> Rep I (tbl f) ~~> Rep (Interpret (d f)) (tbl Uninterpreted) ---- -- Using repLenses we can construct a lens of type -- --
-- Rep (Interpret (d f)) (tbl Uninterpreted) ~~> Interpret (d f) x ---- -- for every field of type x. Putting these two together gives -- us a lens -- --
-- tbl f ~~> Interpret (d f) x ---- -- for every field in tbl Uninterpreted. We cannot simplify -- this, because we do not know anything about the shape of x; -- specifically, it might not be equal to Uninterpreted x' for -- some x', and hence we cannot simplify the target type of the -- lens. We can do better for records with regular fields; see -- lensesForRegularRecord. lensesForHKRecord :: forall d tbl f. (Generic (tbl f), Generic (tbl Uninterpreted), HasNormalForm (d f) (tbl f) (tbl Uninterpreted)) => Proxy d -> Rep (HKRecordLens d f tbl) (tbl Uninterpreted) -- | Lenses into higher-kinded records with regular fields -- -- We can use lensesForHKRecord to construct a Rep of -- lenses into a higher-kinded record. If in addition the record is -- regular, we can use the record type itself to store all the -- lenses. lensesForRegularRecord :: forall d tbl f. (Generic (tbl (RegularRecordLens tbl f)), Generic (tbl Uninterpreted), Generic (tbl f), HasNormalForm (d (RegularRecordLens tbl f)) (tbl (RegularRecordLens tbl f)) (tbl Uninterpreted), HasNormalForm (d f) (tbl f) (tbl Uninterpreted), Constraints (tbl Uninterpreted) (IsRegularField Uninterpreted), StandardInterpretation d (RegularRecordLens tbl f), StandardInterpretation d f) => Proxy d -> tbl (RegularRecordLens tbl f) -- | Proof that x is a regular field -- -- See IsRegularField data RegularField f x [RegularField] :: RegularField f (f x) -- | Regular record fields -- -- For a higher-kinded record tbl f, parameterized over some -- functor f, we say that the fields are regular iff -- every field has the form f x for some x. class IsRegularField f x isRegularField :: IsRegularField f x => Proxy (f x) -> RegularField f x data RepLens f a x [RepLens] :: Lens' (Rep f a) (f x) -> RepLens f a x repLenses :: Generic a => Rep (RepLens f a) a genericLens :: Generic a => Lens' a (Rep I a) normalForm1Lens :: HasNormalForm (d f) (x f) (x Uninterpreted) => Proxy d -> Lens' (Rep I (x f)) (Rep (Interpret (d f)) (x Uninterpreted)) interpretedLens :: Lens' (Interpret d x) (Interpreted d x) standardInterpretationLens :: forall d f x. StandardInterpretation d f => Proxy d -> Lens' (Interpret (d f) (Uninterpreted x)) (f x) instance Data.Record.Generic.Lens.VL.IsRegularField f (f x)