| Copyright | (c) Justin Le 2019 |
|---|---|
| License | BSD3 |
| Maintainer | justin@jle.im |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | Safe-Inferred |
| Language | Haskell2010 |
Data.Functor.Invariant.Inplicative.Free
Description
Synopsis
- newtype DivAp f a where
- runCoDivAp :: forall f g. Applicative g => (f ~> g) -> DivAp f ~> g
- runContraDivAp :: forall f g. Divisible g => (f ~> g) -> DivAp f ~> g
- divApAp :: DivAp f ~> Ap f
- divApDiv :: DivAp f ~> Div f
- foldDivAp :: (forall x. x -> g x) -> (Day f g ~> g) -> DivAp f ~> g
- assembleDivAp :: NP f as -> DivAp f (NP I as)
- assembleDivApRec :: Rec f as -> DivAp f (XRec Identity as)
- newtype DivAp1 f a where
- runCoDivAp1 :: forall f g. Apply g => (f ~> g) -> DivAp1 f ~> g
- runContraDivAp1 :: forall f g. Divise g => (f ~> g) -> DivAp1 f ~> g
- divApAp1 :: DivAp1 f ~> Ap1 f
- divApDiv1 :: DivAp1 f ~> Div1 f
- foldDivAp1 :: (f ~> g) -> (Day f g ~> g) -> DivAp1 f ~> g
- assembleDivAp1 :: Invariant f => NP f (a ': as) -> DivAp1 f (NP I (a ': as))
- assembleDivAp1Rec :: Invariant f => Rec f (a ': as) -> DivAp1 f (XRec Identity (a ': as))
Chain
The invariant version of Ap and Div: combines the capabilities of
both Ap and Div together.
Conceptually you can think of as a way of consuming and
producing DivAp f aas that contains a collection of f xs of different xs.
When interpreting this, each a is distributed across all f xs to
each interpret, and then re-combined again to produce the resulting a.
To do this, the main tools to combine DivAps are its Inply
instance, using gather to combine two DivAps in a choice-like
manner (with the splitting and re-combining function), and its
Inplicative instance, using knot to create an "empty" branch that
does not contribute to the structure.
This does have an Interpret function, but the target typeclass
(Inplicative) doesn't have too many useful instances. Instead, you
are probably going to run it into either Applicative instance (to
"produce" an a from a ) with DivAp f arunCoDivAp, or
a Divisible instance (to "consume" an a from a ) with
DivAp f arunContraDivAp.
If you think of this type as a combination of Ap and Div, then
you can also extract the Ap part out using divApAp, and
extract the Div part out using divApDiv.
Note that this type's utility is similar to that of ,
except PreT Ap lets you use PreT ApApplicative typeclass methods to
assemble it.
Since: 0.3.5.0
Bundled Patterns
| pattern Gather :: (b -> c -> a) -> (a -> (b, c)) -> f b -> DivAp f c -> DivAp f a | Match on a non-empty Note that the order of the first two arguments has swapped as of v0.4.0.0 |
| pattern Knot :: a -> DivAp f a | Match on an "empty" |
Instances
| FreeOf Inplicative DivAp Source # | Since: 0.4.0.0 |
Defined in Data.HFunctor.Final Associated Types type FreeFunctorBy DivAp :: (Type -> Type) -> Constraint Source # | |
| Inplicative (DivAp f) Source # | The free |
Defined in Data.Functor.Invariant.Inplicative.Free | |
| Inply (DivAp f) Source # | |
| Invariant (DivAp f) Source # | |
Defined in Data.HFunctor.Chain.Internal | |
| Inject DivAp Source # | |
| Inplicative f => Interpret DivAp (f :: Type -> TYPE LiftedRep) Source # | A free |
| HTraversable DivAp Source # | |
Defined in Data.HFunctor.Chain.Internal | |
| HFunctor DivAp Source # | |
| type FreeFunctorBy DivAp Source # | |
Defined in Data.HFunctor.Final | |
runCoDivAp :: forall f g. Applicative g => (f ~> g) -> DivAp f ~> g Source #
In the covariant direction, we can interpret into any Applicative.
In theory, this shouldn't never be necessary, because you should just be
able to use interpret, since any instance of Applicative is also an
instance of Inplicative. However, this can be handy if you are using
an instance of Applicative that has no Inplicative instance.
Consider also unsafeInplicativeCo if you are using a specific,
concrete type for g.
runContraDivAp :: forall f g. Divisible g => (f ~> g) -> DivAp f ~> g Source #
In the covariant direction, we can interpret into any Divisible.
In theory, this shouldn't never be necessary, because you should just be
able to use interpret, since any instance of Divisible is also an
instance of Inplicative. However, this can be handy if you are using
an instance of Divisible that has no Inplicative instance. Consider
also unsafeInplicativeContra if you are using a specific, concrete
type for g.
assembleDivAp :: NP f as -> DivAp f (NP I as) Source #
Convenient wrapper to build up a DivAp by providing each
component of it. This makes it much easier to build up longer chains
because you would only need to write the splitting/joining functions in
one place.
For example, if you had a data type
data MyType = MT Int Bool String
and an invariant functor Prim (representing, say, a bidirectional
parser, where Prim Int is a bidirectional parser for an Int),
then you could assemble a bidirectional parser for a MyType@ using:
invmap ((MyType x y z) -> I x :* I y :* I z :* Nil)
((I x :* I y :* I z :* Nil) -> MyType x y z) $
assembleDivAp $ intPrim
:* boolPrim
:* stringPrim
:* Nil
Some notes on usefulness depending on how many components you have:
- If you have 0 components, use
Knotdirectly. - If you have 1 component, use
injectorinjectChaindirectly. - If you have 2 components, use
toListByortoChain. - If you have 3 or more components, these combinators may be useful; otherwise you'd need to manually peel off tuples one-by-one.
If each component is itself a (instead of DivAp ff), you can use
concatInplicative.
assembleDivApRec :: Rec f as -> DivAp f (XRec Identity as) Source #
A version of assembleDivAp using XRec from vinyl instead of
NP from sop-core. This can be more convenient because it doesn't
require manual unwrapping/wrapping of components.
data MyType = MT Int Bool String
invmap ((MyType x y z) -> x ::& y ::& z ::& RNil)
((x ::& y ::& z ::& RNil) -> MyType x y z) $
assembleDivApRec $ intPrim
:& boolPrim
:& stringPrim
:& Nil
If each component is itself a (instead of DivAp ff), you can use
concatDivApRec.
Nonempty Chain
The invariant version of Ap1 and Div1: combines the capabilities
of both Ap1 and Div1 together.
Conceptually you can think of as a way of consuming and
producing DivAp1 f aas that contains a (non-empty) collection of f xs of
different xs. When interpreting this, each a is distributed across
all f xs to each interpret, and then re-combined again to produce the
resulting a.
To do this, the main tools to combine DivAp1s are its Inply
instance, using gather to combine two DivAp1s in
a parallel-fork-like manner (with the splitting and re-combining
function).
This does have an Interpret function, but the target typeclass
(Inply) doesn't have too many useful instances. Instead, you are
probably going to run it into either Apply instance (to "produce" an
a from a ) with DivAp1 f arunCoDivAp1, or a Divise instance
(to "consume" an a from a ) with DivAp1 f arunContraDivAp1.
If you think of this type as a combination of Ap1 and Div1, then
you can also extract the Ap1 part out using divApAp1, and
extract the Div1 part out using divApDiv1.
Note that this type's utility is similar to that of ,
except PreT Ap1 lets you use PreT Ap1Apply typeclass methods to assemble
it.
Since: 0.3.5.0
Bundled Patterns
| pattern DivAp1 :: Invariant f => (b -> c -> a) -> (a -> (b, c)) -> f b -> DivAp f c -> DivAp1 f a | Match on a Note that the order of the first two arguments has swapped as of v0.4.0.0 |
Instances
| FreeOf Inply DivAp1 Source # | Since: 0.4.0.0 |
| Invariant f => Inply (DivAp1 f) Source # | The free |
| Invariant f => Invariant (DivAp1 f) Source # | |
Defined in Data.HFunctor.Chain.Internal | |
| Inject DivAp1 Source # | |
| Inply f => Interpret DivAp1 (f :: Type -> TYPE LiftedRep) Source # | A free |
| HTraversable DivAp1 Source # | |
Defined in Data.HFunctor.Chain.Internal | |
| HTraversable1 DivAp1 Source # | |
Defined in Data.HFunctor.Chain.Internal | |
| HFunctor DivAp1 Source # | |
| type FreeFunctorBy DivAp1 Source # | |
Defined in Data.HFunctor.Final | |
runCoDivAp1 :: forall f g. Apply g => (f ~> g) -> DivAp1 f ~> g Source #
In the covariant direction, we can interpret into any Apply.
In theory, this shouldn't never be necessary, because you should just be
able to use interpret, since any instance of Apply is also an instance
of Inply. However, this can be handy if you are using an instance of
Apply that has no Inply instance. Consider also unsafeInplyCo if
you are using a specific, concrete type for g.
runContraDivAp1 :: forall f g. Divise g => (f ~> g) -> DivAp1 f ~> g Source #
In the contravariant direction, we can interpret into any Divise.
In theory, this shouldn't never be necessary, because you should just be
able to use interpret, since any instance of Divise is also an instance
of Inply. However, this can be handy if you are using an instance of
Divise that has no Inply instance. Consider also
unsafeInplyContra if you are using a specific, concrete type for g.
assembleDivAp1 :: Invariant f => NP f (a ': as) -> DivAp1 f (NP I (a ': as)) Source #
A version of assembleDivAp but for DivAp1 instead. Can be
useful if you intend on interpreting it into something with only
a Divise or Apply instance, but no Divisible or Applicative.
If each component is itself a (instead of DivAp1 ff), you can use
concatInply.
assembleDivAp1Rec :: Invariant f => Rec f (a ': as) -> DivAp1 f (XRec Identity (a ': as)) Source #
A version of assembleDivAp1 using XRec from vinyl instead of
NP from sop-core. This can be more convenient because it doesn't
require manual unwrapping/wrapping of components.
If each component is itself a (instead of DivAp1 ff), you can use
concatDivAp1Rec.
Orphan instances
| Inplicative (DivAp f) Source # | The free |
| Inply (DivAp f) Source # | |
| Invariant f => Inply (DivAp1 f) Source # | The free |
| Inplicative f => Interpret DivAp (f :: Type -> TYPE LiftedRep) Source # | A free |
| Inply f => Interpret DivAp1 (f :: Type -> TYPE LiftedRep) Source # | A free |