-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Familiar functions lifted to generic data types
--
-- Please see README.md.
@package generic-data-functions
@version 0.1.0
-- | Functions "lifted" (roughly) to generic Haskell data types.
--
-- Haskell data types have a fair amount of structure to them:
--
--
-- - Multiple constructors (sums)
-- - Multiple fields (products)
-- - Constructor names must be unique
-- - Fields are ordered left-to-right (or top-to-bottom)
--
--
-- We leverage this structure to provide parameterized generic functions,
-- where the user only handles the base case (individual fields). Such
-- generics are very relevant for simplistic usages like boring type
-- folds and serializing tasks. No need to bash out 50 lines of arcane
-- type algebra -- just write a single instance and you're golden.
--
-- Sum types introduce choice, which brings an extra layer of complexity.
-- For this reason, most functions provide a sum type version and a
-- non-sum type version. Sum type generic functions will require a bit
-- more information, like some extra definitions or instances. Using the
-- wrong one will result in a clear type error.
module Generic.Data.Function
-- | Common descriptions for generic data type errors.
module Generic.Data.Function.Error
-- | Common type error string for when you attempt to use a generic
-- instance at an empty data type (e.g. Void, V1).
type ENoEmpty = 'Text "Requested generic instance disallows empty data type"
-- | Common type error string for when GHC is asked to derive a non-sum
-- instance, but the data type in question turns out to be a sum data
-- type.
--
-- No need to add the data type name here, since GHC's context includes
-- the surrounding instance declaration.
type EUnexpectedSum = 'Text "Cannot derive non-sum generic instance for sum data type"
-- | Common type error string for when GHC is asked to derive a sum
-- instance, but the data type in question turns out to be a non-sum data
-- type.
--
-- No need to add the data type name here, since GHC's context includes
-- the surrounding instance declaration.
type EUnexpectedNonSum = 'Text "Refusing to derive sum generic instance for non-sum data type"
-- | Handy generics utils.
module Generic.Data.Function.Util.Generic
-- | datatypeName without the value (only used as a proxy). Lets us
-- push our undefineds into one place.
datatypeName' :: forall d. Datatype d => String
-- | conName without the value (only used as a proxy). Lets us push
-- our undefineds into one place.
conName' :: forall c. Constructor c => String
-- | selName without the value (only used as a proxy). Lets us push
-- our undefineds into one place.
selName' :: forall s. Selector s => String
-- | Get the record name for a selector if present.
--
-- On the type level, a 'Maybe Symbol' is stored for record names. But
-- the reification is done using fromMaybe "". So we have to
-- inspect the resulting string to determine whether the field uses
-- record syntax or not. (Silly.)
selName'' :: forall s. Selector s => Maybe String
-- | Handy typenat utils.
module Generic.Data.Function.Util.TypeNats
natVal'' :: forall n. KnownNat n => Natural
natValInt :: forall n. KnownNat n => Int
-- | Wrapper types for using with DerivingVia.
module Generic.Data.Function.Via
-- | Wrapper for using to derive instances via generics. Emit type error on
-- Rec0 base case i.e. any non-empty constructor.
newtype NoRec0 a
NoRec0 :: a -> NoRec0 a
[unNoRec0] :: NoRec0 a -> a
type ENoRec0 = 'Text "Cannot use generic function on NoRec0-wrapped type containing fields"
-- | Wrapper for using to derive instances via generics. Do nothing for
-- Rec0 base case i.e. every constructor field.
--
-- "nothing" probably means mempty, but *may* be another
-- unit-like.
--
-- TODO This might not be useful. It's not "special" like NoRec0,
-- it's basically tied to Monoid. So it's useful for
-- foldMap, but kind of arbitrary when applied to traverse.
newtype EmptyRec0 a
EmptyRec0 :: a -> EmptyRec0 a
[unEmptyRec0] :: EmptyRec0 a -> a
instance GHC.Base.Monad Generic.Data.Function.Via.NoRec0
instance GHC.Base.Applicative Generic.Data.Function.Via.NoRec0
instance GHC.Base.Functor Generic.Data.Function.Via.NoRec0
instance GHC.Show.Show a => GHC.Show.Show (Generic.Data.Function.Via.NoRec0 a)
instance GHC.Generics.Generic (Generic.Data.Function.Via.NoRec0 a)
instance GHC.Base.Monad Generic.Data.Function.Via.EmptyRec0
instance GHC.Base.Applicative Generic.Data.Function.Via.EmptyRec0
instance GHC.Base.Functor Generic.Data.Function.Via.EmptyRec0
instance GHC.Show.Show a => GHC.Show.Show (Generic.Data.Function.Via.EmptyRec0 a)
instance GHC.Generics.Generic (Generic.Data.Function.Via.EmptyRec0 a)
module Generic.Data.Function.Traverse.Constructor
data A a
A :: a -> Sum Int -> () -> A a
-- | Applicative functors that can be generically traversed.
class GenericTraverse f where {
-- | The type class providing (applicative) actions for permitted types.
type GenericTraverseC f a :: Constraint;
}
-- | The action in traverse (first argument).
--
-- We include data type metadata because this function is useful for
-- monadic parsers, which can record it in error messages. (We don't do
-- it for foldMap because it's pure.)
genericTraverseAction :: (GenericTraverse f, GenericTraverseC f a) => String -> String -> Maybe String -> Natural -> f a
class GTraverseC cd cc (si :: Natural) f f'
gTraverseC :: GTraverseC cd cc si f f' => f (f' p)
type family ProdArity (f :: Type -> Type) :: Natural
instance GHC.Show.Show a => GHC.Show.Show (Generic.Data.Function.Traverse.Constructor.A a)
instance GHC.Generics.Generic (Generic.Data.Function.Traverse.Constructor.A a)
instance forall k1 k2 (f :: Type -> Type) (cd :: k1) (cc :: k2) (si :: GHC.Num.Natural.Natural) (l :: Type -> Type) (r :: Type -> Type). (GHC.Base.Applicative f, Generic.Data.Function.Traverse.Constructor.GTraverseC cd cc si f l, Generic.Data.Function.Traverse.Constructor.GTraverseC cd cc (si GHC.TypeNats.+ Generic.Data.Function.Traverse.Constructor.ProdArity r) f r) => Generic.Data.Function.Traverse.Constructor.GTraverseC cd cc si f (l GHC.Generics.:*: r)
instance forall k1 k2 k3 (f :: Type -> Type) a (si :: GHC.TypeNats.Nat) (cs :: GHC.Generics.Meta) (cc :: k1) (cd :: k2). (Generic.Data.Function.Traverse.Constructor.GenericTraverse f, Generic.Data.Function.Traverse.Constructor.GenericTraverseC f a, GHC.Base.Functor f, GHC.TypeNats.KnownNat si, GHC.Generics.Selector cs, GHC.Generics.Constructor cc, GHC.Generics.Datatype cd) => Generic.Data.Function.Traverse.Constructor.GTraverseC cd cc si f (GHC.Generics.S1 cs (GHC.Generics.Rec0 a))
instance forall k1 k2 k3 (f :: Type -> Type) (cd :: k1) (cc :: k2). GHC.Base.Applicative f => Generic.Data.Function.Traverse.Constructor.GTraverseC cd cc 0 f GHC.Generics.U1
instance Generic.Data.Function.Traverse.Constructor.GenericTraverse Generic.Data.Function.Via.NoRec0
instance Generic.Data.Function.Traverse.Constructor.GenericTraverse Generic.Data.Function.Via.EmptyRec0
module Generic.Data.Function.Traverse.Sum
-- | Sum-type monads that can be generically traversed.
--
-- For sum types, we require a monad with choice to differentiate
-- constructors.
class (GenericTraverse f, Alternative f, Monad f) => GenericTraverseSum f
-- | Try to parse a prefix tag of type pt.
--
-- Relevant metadata is provided as arguments.
genericTraverseSumPfxTagAction :: (GenericTraverseSum f, GenericTraverseC f pt) => String -> f pt
-- | Parse error due to no constructor matching the parsed prefix tag.
--
-- Relevant metadata is provided as arguments.
genericTraverseSumNoMatchingCstrAction :: GenericTraverseSum f => String -> [String] -> Text -> f a
-- | How to use a type as a prefix tag in a generic sum type parser.
data PfxTagCfg a
PfxTagCfg :: (String -> a) -> (a -> a -> Bool) -> (a -> Text) -> PfxTagCfg a
-- | How to turn a constructor name into a prefix tag.
[pfxTagCfgFromCstr] :: PfxTagCfg a -> String -> a
-- | How to compare prefix tags for equality.
--
-- By shoving this into our generic derivation config, we can avoid
-- adding an insidious Eq constraint. In general, you will want to
-- set this to (==).
[pfxTagCfgEq] :: PfxTagCfg a -> a -> a -> Bool
-- | Make a prefix tag human-readable. show is often appropriate.
[pfxTagCfgShow] :: PfxTagCfg a -> a -> Text
class GTraverseSum f f'
gTraverseSum :: (GTraverseSum f f', GenericTraverseC f pt) => PfxTagCfg pt -> f (f' p)
class GTraverseSum' cd f f'
gTraverseSum' :: (GTraverseSum' cd f f', GenericTraverseC f pt) => PfxTagCfg pt -> f (f' p)
-- | Generic getter (constructor sum level).
class GTraverseCSum cd f f'
gTraverseCSum :: GTraverseCSum cd f f' => PfxTagCfg pt -> pt -> f (f' p)
instance forall k1 k2 (f :: Type -> Type) (cd :: k1) (l :: k2 -> Type) (r :: k2 -> Type). (Generic.Data.Function.Traverse.Sum.GenericTraverseSum f, Generic.Data.Function.Traverse.Sum.GTraverseCSum cd f (l GHC.Generics.:+: r), GHC.Generics.Datatype cd) => Generic.Data.Function.Traverse.Sum.GTraverseSum' cd f (l GHC.Generics.:+: r)
instance forall k1 k2 (f :: Type -> Type) (cd :: k1) (l :: k2 -> Type) (r :: k2 -> Type). (GHC.Base.Functor f, GHC.Base.Alternative f, Generic.Data.Function.Traverse.Sum.GTraverseCSum cd f l, Generic.Data.Function.Traverse.Sum.GTraverseCSum cd f r) => Generic.Data.Function.Traverse.Sum.GTraverseCSum cd f (l GHC.Generics.:+: r)
instance forall k1 k2 (f :: Type -> Type) (cd :: k1) (cc :: GHC.Generics.Meta) (f' :: k2 -> Type). (GHC.Base.Alternative f, Generic.Data.Function.Traverse.Constructor.GTraverseC cd cc 0 f f', GHC.Generics.Constructor cc) => Generic.Data.Function.Traverse.Sum.GTraverseCSum cd f (GHC.Generics.C1 cc f')
instance forall k (f :: Type -> Type) (cd :: GHC.Generics.Meta) (f' :: k -> Type). (GHC.Base.Functor f, Generic.Data.Function.Traverse.Sum.GTraverseSum' cd f f') => Generic.Data.Function.Traverse.Sum.GTraverseSum f (GHC.Generics.D1 cd f')
instance forall k1 k2 (cd :: k1) (f :: Type -> Type) (cc :: GHC.Generics.Meta) (f' :: k2 -> Type). (TypeError ...) => Generic.Data.Function.Traverse.Sum.GTraverseSum' cd f (GHC.Generics.C1 cc f')
instance forall k1 k2 (cd :: k1) (f :: Type -> Type). (TypeError ...) => Generic.Data.Function.Traverse.Sum.GTraverseSum' cd f GHC.Generics.V1
module Generic.Data.Function.Traverse.NonSum
class GTraverseNonSum f f'
gTraverseNonSum :: GTraverseNonSum f f' => f (f' p)
class GTraverseNonSum' cd f f'
gTraverseNonSum' :: GTraverseNonSum' cd f f' => f (f' p)
instance forall k (f :: Type -> Type) (cd :: GHC.Generics.Meta) (f' :: k -> Type). (GHC.Base.Functor f, Generic.Data.Function.Traverse.NonSum.GTraverseNonSum' cd f f') => Generic.Data.Function.Traverse.NonSum.GTraverseNonSum f (GHC.Generics.D1 cd f')
instance forall k1 k2 (cd :: k1) (f :: Type -> Type) (l :: k2 -> Type) (r :: k2 -> Type). (TypeError ...) => Generic.Data.Function.Traverse.NonSum.GTraverseNonSum' cd f (l GHC.Generics.:+: r)
instance forall k1 k2 (f :: Type -> Type) (cd :: k1) (cc :: GHC.Generics.Meta) (f' :: k2 -> Type). (GHC.Base.Functor f, Generic.Data.Function.Traverse.Constructor.GTraverseC cd cc 0 f f') => Generic.Data.Function.Traverse.NonSum.GTraverseNonSum' cd f (GHC.Generics.C1 cc f')
instance forall k1 k2 (cd :: k1) (f :: Type -> Type). (TypeError ...) => Generic.Data.Function.Traverse.NonSum.GTraverseNonSum' cd f GHC.Generics.V1
-- | traverse for generic data types.
--
-- TODO This is harder to conceptualize than generic foldMap. No
-- nice clean explanation yet.
--
-- This function can provide generic support for simple parser-esque
-- types.
module Generic.Data.Function.Traverse
-- | Applicative functors that can be generically traversed.
class GenericTraverse f where {
-- | The type class providing (applicative) actions for permitted types.
type GenericTraverseC f a :: Constraint;
}
-- | The action in traverse (first argument).
--
-- We include data type metadata because this function is useful for
-- monadic parsers, which can record it in error messages. (We don't do
-- it for foldMap because it's pure.)
genericTraverseAction :: (GenericTraverse f, GenericTraverseC f a) => String -> String -> Maybe String -> Natural -> f a
-- | Generic traverse over a term of non-sum data type f a.
--
-- f a must have exactly one constructor.
genericTraverseNonSum :: forall f a. (Generic a, GTraverseNonSum f (Rep a), Functor f) => f a
class GTraverseNonSum f f'
-- | Sum-type monads that can be generically traversed.
--
-- For sum types, we require a monad with choice to differentiate
-- constructors.
class (GenericTraverse f, Alternative f, Monad f) => GenericTraverseSum f
-- | Try to parse a prefix tag of type pt.
--
-- Relevant metadata is provided as arguments.
genericTraverseSumPfxTagAction :: (GenericTraverseSum f, GenericTraverseC f pt) => String -> f pt
-- | Parse error due to no constructor matching the parsed prefix tag.
--
-- Relevant metadata is provided as arguments.
genericTraverseSumNoMatchingCstrAction :: GenericTraverseSum f => String -> [String] -> Text -> f a
-- | How to use a type as a prefix tag in a generic sum type parser.
data PfxTagCfg a
PfxTagCfg :: (String -> a) -> (a -> a -> Bool) -> (a -> Text) -> PfxTagCfg a
-- | How to turn a constructor name into a prefix tag.
[pfxTagCfgFromCstr] :: PfxTagCfg a -> String -> a
-- | How to compare prefix tags for equality.
--
-- By shoving this into our generic derivation config, we can avoid
-- adding an insidious Eq constraint. In general, you will want to
-- set this to (==).
[pfxTagCfgEq] :: PfxTagCfg a -> a -> a -> Bool
-- | Make a prefix tag human-readable. show is often appropriate.
[pfxTagCfgShow] :: PfxTagCfg a -> a -> Text
-- | Generic traverse over a term of sum data type f a.
--
-- f a must have at least two constructors.
--
-- You must provide a configuration for how to handle constructors.
genericTraverseSum :: forall f a pt. (Generic a, GTraverseSum f (Rep a), GenericTraverseC f pt, Functor f) => PfxTagCfg pt -> f a
class GTraverseSum f f'
-- | Construct a prefix tag config using existing Eq and Show
-- instances.
--
-- The user only needs to provide the constructor name parser.
eqShowPfxTagCfg :: (Eq a, Show a) => (String -> a) -> PfxTagCfg a
module Generic.Data.Function.FoldMap.Constructor
-- | Monoids that can be generically foldMapped to.
class GenericFoldMap m where {
-- | The type class that enables mapping permitted types to the monoid.
--
-- The type class should provide a function that looks like
-- genericFoldMapF.
type GenericFoldMapC m a :: Constraint;
}
-- | The "map" function in foldMap (first argument).
genericFoldMapF :: (GenericFoldMap m, GenericFoldMapC m a) => a -> m
-- | foldMap on individual constructors (products).
class GFoldMapC m f
gFoldMapC :: GFoldMapC m f => f p -> m
instance forall k m (l :: k -> Type) (r :: k -> Type). (GHC.Base.Semigroup m, Generic.Data.Function.FoldMap.Constructor.GFoldMapC m l, Generic.Data.Function.FoldMap.Constructor.GFoldMapC m r) => Generic.Data.Function.FoldMap.Constructor.GFoldMapC m (l GHC.Generics.:*: r)
instance (Generic.Data.Function.FoldMap.Constructor.GenericFoldMap m, Generic.Data.Function.FoldMap.Constructor.GenericFoldMapC m a) => Generic.Data.Function.FoldMap.Constructor.GFoldMapC m (GHC.Generics.S1 c (GHC.Generics.Rec0 a))
instance GHC.Base.Monoid m => Generic.Data.Function.FoldMap.Constructor.GFoldMapC m GHC.Generics.U1
instance Generic.Data.Function.FoldMap.Constructor.GenericFoldMap (Generic.Data.Function.Via.NoRec0 m)
instance GHC.Base.Monoid m => Generic.Data.Function.FoldMap.Constructor.GenericFoldMap (Generic.Data.Function.Via.EmptyRec0 m)
module Generic.Data.Function.FoldMap.Sum
class GFoldMapSum m f
gFoldMapSum :: GFoldMapSum m f => (String -> m) -> f p -> m
class GFoldMapCSum m f
gFoldMapCSum :: GFoldMapCSum m f => (String -> m) -> f p -> m
instance forall k m (l :: k -> Type) (r :: k -> Type). Generic.Data.Function.FoldMap.Sum.GFoldMapCSum m (l GHC.Generics.:+: r) => Generic.Data.Function.FoldMap.Sum.GFoldMapSum m (l GHC.Generics.:+: r)
instance forall k m (l :: k -> Type) (r :: k -> Type). (Generic.Data.Function.FoldMap.Sum.GFoldMapCSum m l, Generic.Data.Function.FoldMap.Sum.GFoldMapCSum m r) => Generic.Data.Function.FoldMap.Sum.GFoldMapCSum m (l GHC.Generics.:+: r)
instance forall k m (c :: GHC.Generics.Meta) (f :: k -> Type). (GHC.Base.Semigroup m, GHC.Generics.Constructor c, Generic.Data.Function.FoldMap.Constructor.GFoldMapC m f) => Generic.Data.Function.FoldMap.Sum.GFoldMapCSum m (GHC.Generics.C1 c f)
instance forall k m (f :: k -> Type) (c :: GHC.Generics.Meta). Generic.Data.Function.FoldMap.Sum.GFoldMapSum m f => Generic.Data.Function.FoldMap.Sum.GFoldMapSum m (GHC.Generics.D1 c f)
instance forall k m (c :: GHC.Generics.Meta) (f :: k -> Type). (TypeError ...) => Generic.Data.Function.FoldMap.Sum.GFoldMapSum m (GHC.Generics.C1 c f)
instance (TypeError ...) => Generic.Data.Function.FoldMap.Sum.GFoldMapSum m GHC.Generics.V1
module Generic.Data.Function.FoldMap.NonSum
-- | foldMap over generic product data types.
--
-- Take a generic representation, map each field in the data type to a
-- Monoid, and combine the results with (<>).
class GFoldMapNonSum m f
gFoldMapNonSum :: GFoldMapNonSum m f => f p -> m
instance forall k m (f :: k -> Type) (c :: GHC.Generics.Meta). Generic.Data.Function.FoldMap.NonSum.GFoldMapNonSum m f => Generic.Data.Function.FoldMap.NonSum.GFoldMapNonSum m (GHC.Generics.D1 c f)
instance forall k m (l :: k -> Type) (r :: k -> Type). (TypeError ...) => Generic.Data.Function.FoldMap.NonSum.GFoldMapNonSum m (l GHC.Generics.:+: r)
instance forall k m (f :: k -> Type) (c :: GHC.Generics.Meta). Generic.Data.Function.FoldMap.Constructor.GFoldMapC m f => Generic.Data.Function.FoldMap.NonSum.GFoldMapNonSum m (GHC.Generics.C1 c f)
instance (TypeError ...) => Generic.Data.Function.FoldMap.NonSum.GFoldMapNonSum m GHC.Generics.V1
-- | foldMap for generic data types.
--
-- foldMap can be considered a two-step process:
--
--
-- - map every element a of a t a (where
-- Foldable t) to some Monoid m
-- - combine elements using (<>)
--
--
-- Applying this to generic data types:
--
--
-- - map every field of a constructor to some Monoid
-- m
-- - combine elements using (<>)
--
--
-- Field mappings are handled using a per-monoid type class. You need a
-- monoid m with an associated type class which has a function
-- a -> m. Write a GenericFoldMap instance for your
-- monoid which points to your type class. If a field type doesn't have a
-- matching instance, the generic instance emits a type error.
--
-- Sum types (with multiple constructors) are handled by
-- (<>)-ing the constructor with its contents (in that
-- order). You must provide a String -> m function for
-- mapping constructor names. If you need custom sum type handling, you
-- may write your own and still leverage the individual constructor
-- generics.
--
-- This function can provide generic support for simple fold-y operations
-- like serialization.
module Generic.Data.Function.FoldMap
-- | Monoids that can be generically foldMapped to.
class GenericFoldMap m where {
-- | The type class that enables mapping permitted types to the monoid.
--
-- The type class should provide a function that looks like
-- genericFoldMapF.
type GenericFoldMapC m a :: Constraint;
}
-- | The "map" function in foldMap (first argument).
genericFoldMapF :: (GenericFoldMap m, GenericFoldMapC m a) => a -> m
-- | Generic foldMap over a term of non-sum data type a.
--
-- a must have exactly one constructor.
genericFoldMapNonSum :: forall m a. (Generic a, GFoldMapNonSum m (Rep a)) => a -> m
-- | foldMap over generic product data types.
--
-- Take a generic representation, map each field in the data type to a
-- Monoid, and combine the results with (<>).
class GFoldMapNonSum m f
-- | Generic foldMap over a term of sum data type a.
--
-- a must have at least two constructors.
--
-- You must provide a function for mapping constructor names to monoidal
-- values.
genericFoldMapSum :: forall m a. (Generic a, GFoldMapSum m (Rep a)) => (String -> m) -> a -> m
class GFoldMapSum m f