Copyright | (c) Justin Le 2019 |
---|---|
License | BSD3 |
Maintainer | justin@jle.im |
Stability | experimental |
Portability | non-portable |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
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 aa
s that contains a collection of f x
s of different x
s.
When interpreting this, each a
is distributed across all f x
s to
each interpret, and then re-combined again to produce the resulting a
.
To do this, the main tools to combine DivAp
s are its Inply
instance, using gather
to combine two DivAp
s 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
Ap
Applicative
typeclass methods to
assemble it.
Since: 0.3.5.0
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 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
Knot
directly. - If you have 1 component, use
inject
orinjectChain
directly. - If you have 2 components, use
toListBy
ortoChain
. - 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 aa
s that contains a (non-empty) collection of f x
s of
different x
s. When interpreting this, each a
is distributed across
all f x
s to each interpret, and then re-combined again to produce the
resulting a
.
To do this, the main tools to combine DivAp1
s are its Inply
instance, using gather
to combine two DivAp1
s 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
Ap1
Apply
typeclass methods to assemble
it.
Since: 0.3.5.0
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 |