| Copyright | (c) Justin Le 2019 | 
|---|---|
| License | BSD3 | 
| Maintainer | justin@jle.im | 
| Stability | experimental | 
| Portability | non-portable | 
| Safe Haskell | Safe-Inferred | 
| Language | Haskell2010 | 
Data.HFunctor.Route
Description
This module contains the useful combinators Pre and Post, which
 enhances a functor with a "route" to and from the outside world; even if
 the functor itself is existentially closed in a functor combinator, the
 route will provide line to the outside world for extraction or
 injection.
See Pre and Post for more information.
Since: 0.3.4.0
Synopsis
- data Pre a f b = (a -> b) :>$<: (f b)
- interpretPre :: Contravariant g => (f ~> g) -> Pre a f b -> g a
- getPre :: Pre a f b -> f b
- retractPre :: Contravariant f => Pre a f b -> f a
- injectPre :: Inject t => (a -> b) -> f b -> t (Pre a f) b
- mapPre :: (c -> a) -> Pre a f b -> Pre c f b
- preDivisible :: (forall m. Monoid m => Interpret t (AltConst m), Divisible g) => (f ~> g) -> t (Pre a f) b -> g a
- preDivise :: (forall m. Semigroup m => Interpret t (AltConst m), Divise g) => (f ~> g) -> t (Pre a f) b -> g a
- preContravariant :: (forall m. Interpret t (AltConst m), Contravariant g) => (f ~> g) -> t (Pre a f) b -> g a
- data Post a f b = (b -> a) :<$>: (f b)
- interpretPost :: Functor g => (f ~> g) -> Post a f b -> g a
- getPost :: Post a f b -> f b
- retractPost :: Functor f => Post a f b -> f a
- injectPost :: Inject t => (b -> a) -> f b -> t (Post a f) b
- mapPost :: (a -> c) -> Post a f b -> Post c f b
- postPlus :: (forall m. Monoid m => Interpret t (AltConst m), Plus g) => (f ~> g) -> t (Post a f) b -> g a
- postAlt :: (forall m. Semigroup m => Interpret t (AltConst m), Alt g) => (f ~> g) -> t (Post a f) b -> g a
- postFunctor :: (forall m. Interpret t (AltConst m), Functor g) => (f ~> g) -> t (Post a f) b -> g a
- newtype PreT t f a = PreT {}
- preDivisibleT :: (forall m. Monoid m => Interpret t (AltConst m), Divisible g) => (f ~> g) -> PreT t f ~> g
- preDiviseT :: (forall m. Semigroup m => Interpret t (AltConst m), Divise g) => (f ~> g) -> PreT t f ~> g
- preContravariantT :: (forall m. Interpret t (AltConst m), Contravariant g) => (f ~> g) -> PreT t f ~> g
- newtype PostT t f a = PostT {}
- postPlusT :: (forall m. Monoid m => Interpret t (AltConst m), Plus g) => (f ~> g) -> PostT t f ~> g
- postAltT :: (forall m. Semigroup m => Interpret t (AltConst m), Alt g) => (f ~> g) -> PostT t f ~> g
- postFunctorT :: (forall m. Interpret t (AltConst m), Functor g) => (f ~> g) -> PostT t f ~> g
Routing Combinators
Contravariant
A useful helper type to use with a covariant functor combinator that
 allows you to tag along contravariant access to all fs inside the
 combinator.
Maybe most usefully, it can be used with Ap.  Remember that Ap f af xs, with each x existentially wrapped.  Now, for
 a Ap (Pre a f) af x and a -> xs:
 not only each individual part, but a way to "select" that individual
 part from the overal a.
So, you can imagine Ap (Pre a f) bf x that
 consumes a and produces b.
When a and b are the same, Ap (Pre a f) aAp (Pre a f) aas and also producing as.
You can build up these values with injectPre, and then use whatever
 typeclasses your t normally supports to build it up, like
 Applicative (for Ap).  You can then interpret it into both its
 contravariant and covariant contexts:
-- interpret the covariant part runCovariant ::Applicativeg => (f ~> g) -> Ap (Pre a f) a -> g a runCovariant f = interpret (f . getPre) -- interpret the contravariant part runContravariant ::Divisibleg => (f ~> g) -> Ap (Pre a f) a -> g a runContravariant = preDivisible
The PreT type wraps up Ap (Pre a f) aPreT Ap
 f a
An example of a usage of this in the real world is the unjson library's record type constructor, to implement bidrectional serializers for product types.
Constructors
| (a -> b) :>$<: (f b) infixl 4 | 
Instances
| HTraversable (Pre a :: (Type -> Type) -> Type -> Type) Source # | |
| Defined in Data.HFunctor.Route | |
| HFunctor (Pre a :: (Type -> Type) -> Type -> Type) Source # | |
| a ~ Void => HBind (Pre a :: (Type -> Type) -> Type -> Type) Source # | This instance is over-contrained ( | 
| a ~ Void => Inject (Pre a :: (Type -> Type) -> Type -> Type) Source # | This instance is over-contrained ( | 
| a ~ Void => Interpret (Pre a :: (Type -> Type) -> Type -> Type) (f :: Type -> Type) Source # | |
| Functor f => Functor (Pre a f) Source # | |
| Contravariant f => Invariant (Pre a f) Source # | |
| Defined in Data.HFunctor.Route | |
interpretPre :: Contravariant g => (f ~> g) -> Pre a f b -> g a Source #
Interpret a Pre into a contravariant context, applying the
 pre-routing function.
getPre :: Pre a f b -> f b Source #
Drop the pre-routing function and just give the original wrapped value.
retractPre :: Contravariant f => Pre a f b -> f a Source #
injectPre :: Inject t => (a -> b) -> f b -> t (Pre a f) b Source #
Like inject, but allowing you to provide a pre-routing function.
preDivisible :: (forall m. Monoid m => Interpret t (AltConst m), Divisible g) => (f ~> g) -> t (Pre a f) b -> g a Source #
Run a "pre-routed" t into a contravariant Divisible context.  To
 run it in ts normal covariant context, use interpret with getPre.
This will work for types where there are a possibly-empty collection of
 fs, like:
preDivisible :: Divisible g => (f ~> g) ->Ap(Prea f) b -> g a preDivisible :: Divisible g => (f ~> g) ->ListF(Prea f) b -> g a
preDivise :: (forall m. Semigroup m => Interpret t (AltConst m), Divise g) => (f ~> g) -> t (Pre a f) b -> g a Source #
Run a "pre-routed" t into a contravariant Divise context.  To
 run it in ts normal covariant context, use interpret with getPre.
This will work for types where there are is a non-empty collection of
 fs, like:
preDivise :: Divise g => (f ~> g) ->Ap1(Prea f) b -> g a preDivise :: Divise g => (f ~> g) ->NonEmptyF(Prea f) b -> g a
preContravariant :: (forall m. Interpret t (AltConst m), Contravariant g) => (f ~> g) -> t (Pre a f) b -> g a Source #
Run a "pre-routed" t into a Contravariant.  To run it in ts
 normal covariant context, use interpret with getPre.
This will work for types where there is exactly one f inside:
preContravariant :: Contravariant g => (f ~> g) ->Step(Prea f) b -> g a preContravariant :: Contravariant g => (f ~> g) ->Coyoneda(Prea f) b -> g a
Covariant
A useful helper type to use with a contravariant functor combinator that
 allows you to tag along covariant access to all fs inside the
 combinator.
Maybe most usefully, it can be used with Dec.  Remember that Dec f af xs, with each x existentially wrapped.  Now, for
 a Dec (Post a f) af x and x -> as:
 not only each individual part, but a way to "re-embed" that individual
 part into overal a.
So, you can imagine Dec (Post a f) bf x that
 consumes b and produces a.
When a and b are the same, Dec (Post a f) aDec (Post a f) aas and also producing as.
You can build up these values with injectPre, and then use whatever
 typeclasses your t normally supports to build it up, like
 Conclude (for Div).  You can then interpret it into both its
 contravariant and covariant contexts:
-- interpret the covariant part runCovariant ::Plusg => (f ~> g) -> Div (Post a f) a -> g a runCovariant f = interpret (f . getPost) -- interpret the contravariant part runContravariant ::Concludeg => (f ~> g) -> Div (Post a f) a -> g a runContravariant = preDivisible
The PostT type wraps up Dec (Post a f) aPostT
 Dec
 f a
An example of a usage of this in the real world is a possible implementation of the unjson library's sum type constructor, to implement bidrectional serializers for sum types.
Constructors
| (b -> a) :<$>: (f b) infixl 4 | 
Instances
| HTraversable (Post a :: (Type -> Type) -> Type -> Type) Source # | |
| Defined in Data.HFunctor.Route | |
| HFunctor (Post a :: (Type -> Type) -> Type -> Type) Source # | |
| Monoid a => HBind (Post a :: (Type -> Type) -> Type -> Type) Source # | |
| Monoid a => Inject (Post a :: (Type -> Type) -> Type -> Type) Source # | |
| Monoid a => Interpret (Post a :: (Type -> Type) -> Type -> Type) (f :: Type -> Type) Source # | |
| Contravariant f => Contravariant (Post a f) Source # | |
| Functor f => Invariant (Post a f) Source # | |
| Defined in Data.HFunctor.Route | |
interpretPost :: Functor g => (f ~> g) -> Post a f b -> g a Source #
Interpret a Post into a covariant context, applying the
 post-routing function.
getPost :: Post a f b -> f b Source #
Drop the post-routing function and just give the original wrapped value.
retractPost :: Functor f => Post a f b -> f a Source #
injectPost :: Inject t => (b -> a) -> f b -> t (Post a f) b Source #
Like inject, but allowing you to provide a post-routing function.
postPlus :: (forall m. Monoid m => Interpret t (AltConst m), Plus g) => (f ~> g) -> t (Post a f) b -> g a Source #
Run a "post-routed" t into a covariant Plus context.  To run it
 in ts normal contravariant context, use interpret.
This will work for types where there are a possibly-empty collection of
 fs, like:
postPlus :: Plus g => (f ~> g) ->Dec(Post a f) b -> g a postPlus :: Plus g => (f ~> g) ->Div(Post a f) b -> g a
postAlt :: (forall m. Semigroup m => Interpret t (AltConst m), Alt g) => (f ~> g) -> t (Post a f) b -> g a Source #
Run a "post-routed" t into a covariant Alt context.  To run it
 in ts normal contravariant context, use interpret.
This will work for types where there are is a non-empty collection of
 fs, like:
postAlt :: Alt g => (f ~> g) ->Dec1(Post a f) b -> g a postAlt :: Alt g => (f ~> g) ->Div1(Post a f) b -> g a
postFunctor :: (forall m. Interpret t (AltConst m), Functor g) => (f ~> g) -> t (Post a f) b -> g a Source #
Run a "post-routed" t into a covariant Functor context.  To run it
 in ts normal contravariant context, use interpret.
This will work for types where there is exactly one f inside:
postFunctor :: Functor g => (f ~> g) ->Step(Post a f) b -> g a postFunctor :: Functor g => (f ~> g) ->Coyoneda(Post a f) b -> g a
Wrapped Invariant
Contravariant
Turn the covariant functor combinator t into an Invariant
 functor combinator; if t f a "produces" as, then PreT t f aas.
You can run this normally as if it were a t f a by using interpret;
 however, you can also interpret into covariant contexts with
 preDivisibleT, preDiviseT, and preContravariantT.
A useful way to use this type is to use normal methods of the underlying
 t to assemble a final t, then using the PreT constructor to wrap
 it all up.
data MyType = MyType
     { mtInt    :: Int
     , mtBool   :: Bool
     , mtString :: String
     }
myThing :: PreT Ap MyFunctor MyType
myThing = PreT $ MyType
    $ injectPre mtInt    (mfInt    :: MyFunctor Int   )
    * injectPre mtBool   (mfBool   :: MyFunctor Bool  )
    * injectPre mtString (mfString :: MyFunctor STring)
See Pre for more information.
Instances
| HTraversable t => HTraversable (PreT t :: (Type -> Type) -> Type -> Type) Source # | |
| Defined in Data.HFunctor.Route | |
| HFunctor t => HFunctor (PreT t :: (Type -> Type) -> Type -> Type) Source # | |
| Inject t => Inject (PreT t :: (Type -> Type) -> Type -> Type) Source # | |
| Interpret t f => Interpret (PreT t :: (Type -> Type) -> Type -> Type) (f :: Type -> Type) Source # | |
| (HFunctor t, forall x. Functor (t (Pre x f))) => Invariant (PreT t f) Source # | |
| Defined in Data.HFunctor.Route | |
preDivisibleT :: (forall m. Monoid m => Interpret t (AltConst m), Divisible g) => (f ~> g) -> PreT t f ~> g Source #
Run a PreT tDivisible context.  To run it
 in ts normal covariant context, use interpret.
This will work for types where there are a possibly-empty collection of
 fs, like:
preDivisibleT :: Divisible g => (f ~> g) -> PreTApf ~> g preDivisibleT :: Divisible g => (f ~> g) -> PreTListFf ~> g
preDiviseT :: (forall m. Semigroup m => Interpret t (AltConst m), Divise g) => (f ~> g) -> PreT t f ~> g Source #
preContravariantT :: (forall m. Interpret t (AltConst m), Contravariant g) => (f ~> g) -> PreT t f ~> g Source #
Run a PreT tContravariant.  To run it in
 ts normal covariant context, use interpret.
This will work for types where there is exactly one f inside:
preContravariantT :: Contravariant g => (f ~> g) -> PreTStepf ~> g preContravariantT :: Contravariant g => (f ~> g) -> PreTCoyonedaf ~> g
Covariant
Turn the contravariant functor combinator t into an Invariant
 functor combinator; if t f a "consumes" as, then PostT t f aas.
You can run this normally as if it were a t f a by using interpret;
 however, you can also interpret into covariant contexts with
 postPlusT, postAltT, and postFunctorT.
A useful way to use this type is to use normal methods of the underlying
 t to assemble a final t, then using the PreT constructor to wrap
 it all up.
myThing :: PostT Dec MyFunctor (Either Int Bool)
myThing = PostT $ decided $
    (injectPost Left  (mfInt  :: MyFunctor Int ))
    (injectPost Right (mfBool :: MyFunctor Bool))
See Post for more information.
Instances
| HTraversable t => HTraversable (PostT t :: (Type -> Type) -> Type -> Type) Source # | |
| Defined in Data.HFunctor.Route | |
| HFunctor t => HFunctor (PostT t :: (Type -> Type) -> Type -> Type) Source # | Since: 0.3.4.2 | 
| Inject t => Inject (PostT t :: (Type -> Type) -> Type -> Type) Source # | Since: 0.3.4.2 | 
| Interpret t f => Interpret (PostT t :: (Type -> Type) -> Type -> Type) (f :: Type -> Type) Source # | Since: 0.3.4.2 | 
| (HFunctor t, forall x. Contravariant (t (Post x f))) => Invariant (PostT t f) Source # | |
| Defined in Data.HFunctor.Route | |
postPlusT :: (forall m. Monoid m => Interpret t (AltConst m), Plus g) => (f ~> g) -> PostT t f ~> g Source #
postAltT :: (forall m. Semigroup m => Interpret t (AltConst m), Alt g) => (f ~> g) -> PostT t f ~> g Source #