Copyright | (c) Justin Le 2021 |
---|---|
License | BSD3 |
Maintainer | justin@jle.im |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
Contains the classes Inply
and Inplicative
, the invariant
counterparts to Apply
Divise
and Applicative
Divisible
.
Since: 0.4.0.0
Synopsis
- class Invariant f => Inply f where
- class Inply f => Inplicative f where
- knot :: a -> f a
- runDay :: Inply h => (f ~> h) -> (g ~> h) -> Day f g ~> h
- dather :: Inply f => Day f f ~> f
- concatInplicative :: Inplicative f => NP f as -> f (NP I as)
- concatInply :: Inply f => NP f (a ': as) -> f (NP I (a ': as))
- concatInplicativeRec :: Inplicative f => Rec f as -> f (XRec Identity as)
- concatInplyRec :: Inply f => Rec f (a ': as) -> f (XRec Identity (a ': as))
Typeclass
class Invariant f => Inply f where Source #
The invariant counterpart of Apply
and Divise
.
Conceptually you can think of Apply
as, given a way to "combine" a
and
b
to c
, lets you merge f a
(producer of a
) and f b
(producer
of b
) into a f c
(producer of c
). Divise
can be thought of as,
given a way to "split" a c
into an a
and a b
, lets you merge f
a
(consumer of a
) and f b
(consumder of b
) into a f c
(consumer
of c
).
Inply
, for gather
, requires both a combining function and
a splitting function in order to merge f b
(producer and consumer of
b
) and f c
(producer and consumer of c
) into a f a
. You can
think of it as, for the f a
, it "splits" the a into b
and c
with
the a -> (b, c)
, feeds it to the original f b
and f c
, and then
re-combines the output back into a a
with the b -> c -> a
.
Since: 0.4.0.0
gather :: (b -> c -> a) -> (a -> (b, c)) -> f b -> f c -> f a Source #
Like <.>
, <*>
, divise
, or divide
, but requires both
a splitting and a recombining function. <.>
and <*>
require
only a combining function, and divise
and divide
require only
a splitting function.
It is used to merge f b
(producer and consumer of b
) and f c
(producer and consumer of c
) into a f a
. You can think of it
as, for the f a
, it "splits" the a into b
and c
with the a ->
(b, c)
, feeds it to the original f b
and f c
, and then
re-combines the output back into a a
with the b -> c -> a
.
An important property is that it will always use both
of the
ccomponents given in order to fulfil its job. If you gather an f
a
and an f b
into an f c
, in order to consume/produdce the c
,
it will always use both the f a
or the f b
-- exactly one of
them.
Since: 0.4.0.0
gathered :: f a -> f b -> f (a, b) Source #
A simplified version of gather
that combines into a tuple. You
can then use invmap
to reshape it into the proper shape.
Since: 0.4.0.0
Instances
FreeOf Inply DivAp1 Source # | Since: 0.4.0.0 |
Inply (DivAp f) Source # | |
Invariant f => Inply (DivAp1 f) Source # | The free |
Invariant (Final Inply f) | Since: 0.4.0.0 |
Invariant f => Inply (Chain1 Day f) Source # | Since: 0.4.0.0 |
Inply (Final Inplicative f) Source # | Since: 0.4.0.0 |
Defined in Data.HFunctor.Final gather :: (b -> c -> a) -> (a -> (b, c)) -> Final Inplicative f b -> Final Inplicative f c -> Final Inplicative f a Source # gathered :: Final Inplicative f a -> Final Inplicative f b -> Final Inplicative f (a, b) Source # | |
Inply (Final Inply f) Source # | Since: 0.4.0.0 |
Inply (Final Internative f) Source # | Since: 0.4.0.0 |
Defined in Data.HFunctor.Final gather :: (b -> c -> a) -> (a -> (b, c)) -> Final Internative f b -> Final Internative f c -> Final Internative f a Source # gathered :: Final Internative f a -> Final Internative f b -> Final Internative f (a, b) Source # | |
Inply (Chain Day Identity f) Source # | Since: 0.4.0.0 |
class Inply f => Inplicative f where Source #
The invariant counterpart of Applicative
and Divisible
.
The main important action is described in Inply
, but this adds knot
,
which is the counterpart to pure
and conquer
. It's the identity to
gather
; if combine two f a
s with gather
, and one of them is
knot
, it will leave the structure unchanged.
Conceptually, if you think of gather
as "splitting and re-combining"
along multiple forks, then knot
introduces a fork that is never taken.
Since: 0.4.0.0
Instances
Invariant Day
runDay :: Inply h => (f ~> h) -> (g ~> h) -> Day f g ~> h Source #
Interpret out of a contravariant Day
into any instance of Inply
by
providing two interpreting functions.
This should go in Data.Functor.Invariant.Day, but that module is in a different package.
Since: 0.4.0.0
dather :: Inply f => Day f f ~> f Source #
Squash the two items in a Day
using their natural Inply
instances.
This should go in Data.Functor.Invariant.Day, but that module is in a different package.
Since: 0.4.0.0
Assembling Helpers
concatInplicative :: Inplicative f => NP f as -> f (NP I as) Source #
Convenient wrapper to build up an Inplicative
instance 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 and Inplicative
instance 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) $ concatInplicative $ 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
directly. - If you have 2 components, use
gather
directly. - If you have 3 or more components, these combinators may be useful; otherwise you'd need to manually peel off tuples one-by-one.
Since: 0.4.0.0
concatInply :: Inply f => NP f (a ': as) -> f (NP I (a ': as)) Source #
A version of concatInplicative
for non-empty NP
, but only
requiring an Inply
instance.
Since: 0.4.0.0
concatInplicativeRec :: Inplicative f => Rec f as -> f (XRec Identity as) Source #
A version of concatInplicative
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.
Since: 0.4.0.0
concatInplyRec :: Inply f => Rec f (a ': as) -> f (XRec Identity (a ': as)) Source #
A version of concatInply
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.
Since: 0.4.0.0