| Copyright | (c) Justin Le 2019 |
|---|---|
| License | BSD3 |
| Maintainer | [email protected] |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| 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
is a collection of Ap f af xs, with each x existentially wrapped. Now, for
a , it will be a collection of 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 as a collection of Ap (Pre a f) bf x that
consumes a and produces b.
When a and b are the same, is like the free
invariant sequencer. That is, in a sense, Ap (Pre a f) a contains
both contravariant and covariant sequences side-by-side, consuming
Ap (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 into a type Ap (Pre a f) a, with nice instances/helpers.PreT 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
| 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 # | |
| HFunctor (Pre a :: (Type -> Type) -> Type -> Type) Source # | |
| HTraversable (Pre a :: (Type -> Type) -> Type -> Type) Source # | |
Defined in Data.HFunctor.Route | |
| 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
is a collection of Dec f af xs, with each x existentially wrapped. Now, for
a , it will be a collection of 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 as a collection of Dec (Post a f) bf x that
consumes b and produces a.
When a and b are the same, is like the free
invariant sequencer. That is, in a sense, Dec (Post a f) a contains
both contravariant and covariant sequences side-by-side, consuming
Dec (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 into a type Dec (Post a f) a, with nice instances/helpers.PostT
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
| 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 # | |
| HFunctor (Post a :: (Type -> Type) -> Type -> Type) Source # | |
| HTraversable (Post a :: (Type -> Type) -> Type -> Type) Source # | |
Defined in Data.HFunctor.Route | |
| 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 will
both consume and produce 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
| 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 => HFunctor (PreT t :: (Type -> Type) -> Type -> Type) Source # | |
| HTraversable t => HTraversable (PreT t :: (Type -> Type) -> Type -> Type) Source # | |
Defined in Data.HFunctor.Route | |
| (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 into a contravariant 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 into 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 will
both consume and produce 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
| 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 => HFunctor (PostT t :: (Type -> Type) -> Type -> Type) Source # | Since: 0.3.4.2 |
| HTraversable t => HTraversable (PostT t :: (Type -> Type) -> Type -> Type) Source # | |
Defined in Data.HFunctor.Route | |
| (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 #