| Copyright | (c) Justin Le 2021 |
|---|---|
| License | BSD3 |
| Maintainer | [email protected] |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.Functor.Invariant.Internative
Contents
Description
Synopsis
- class Invariant f => Inalt f where
- class Inalt f => Inplus f where
- class (Inplus f, Inplicative f) => Internative f
- concatInplus :: Inplus f => NP f as -> f (NS I as)
- concatInalt :: Inalt f => NP f (a ': as) -> f (NS I (a ': as))
Typeclass
class Invariant f => Inalt f where Source #
The invariant counterpart of Alt and Decide.
Conceptually you can think of Alt as, given a way to "inject" a and
b as c, lets you merge f a (producer of a) and f b (producer
of b) into a f c (producer of c), in an "either-or" fashion.
Decide can be thought of as, given a way to "discriminate" a c as
either a a or a b, lets you merge f a (consumer of a) and f b
(consumder of b) into a f c (consumer of c) in an "either-or"
forking fashion (split the c into a or b, and use the appropriate
handler).
Inalt, for swerve, requires both an injecting function and
a choosing function in order to merge f b (producer and consumer of
b) and f c (producer and consumer of c) into a f a in an
either-or manner. You can think of it as, for the f a, it "chooses"
if the a is actually a b or a c with the a -> ,
feeds it to either the original Either b cf b or the original f c, and then
re-injects the output back into a a with the b -> a or the c -> a.
Since: 0.4.0.0
Methods
swerve :: (b -> a) -> (c -> a) -> (a -> Either b c) -> f b -> f c -> f a Source #
Like <!>, decide, or choose, but requires both
an injecting and a choosing 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 in an either-or manner.
You can think of it as, for the f a, it "chooses" if the a is
actually a b or a c with the a -> , feeds it to
either the original Either b cf b or the original f c, and then re-injects
the output back into a a with the b -> a or the c -> a.
An important property is that it will only ever use exactly one of
the options given in order to fulfil its job. If you swerve an f
a and an f b into an f c, in order to consume/produdce the c,
it will only use either the f a or the f b -- exactly one of
them.
Since: 0.4.0.0
swerved :: f a -> f b -> f (Either a b) Source #
A simplified version of swerive that splits to and from an
Either. You can then use invmap to reshape it into the proper
shape.
Since: 0.4.0.0
Instances
| FreeOf Inalt DecAlt1 Source # | Since: 0.4.0.0 |
| Inalt (DecAlt f) Source # | |
| Invariant f => Inalt (DecAlt1 f) Source # | |
| Invariant (Final Inalt f) | Since: 0.4.0.0 |
| Invariant f => Inalt (Chain1 Night f) Source # | Since: 0.4.0.0 |
| Inalt (Final Internative f) Source # | Since: 0.4.0.0 |
Defined in Data.HFunctor.Final Methods swerve :: (b -> a) -> (c -> a) -> (a -> Either b c) -> Final Internative f b -> Final Internative f c -> Final Internative f a Source # swerved :: Final Internative f a -> Final Internative f b -> Final Internative f (Either a b) Source # | |
| Inalt (Final Inplus f) Source # | Since: 0.4.0.0 |
| Inalt (Final Inalt f) Source # | Since: 0.4.0.0 |
| Inalt (Chain Night Not f) Source # | Since: 0.4.0.0 |
class Inalt f => Inplus f where Source #
The invariant counterpart of Alt and Conclude.
The main important action is described in Inalt, but this adds reject,
which is the counterpart to empty and conclude and conquer. It's the identity to
swerve; if combine two f as with swerve, and one of them is
reject, then that banch will never be taken.
Conceptually, if you think of swerve as "choosing one path and
re-injecting back", then reject introduces a branch that is impossible
to take.
Instances
| FreeOf Inplus DecAlt Source # | Since: 0.4.0.0 |
| Inplus (DecAlt f) Source # | |
| Invariant (Final Inplus f) | Since: 0.4.0.0 |
| Inplus (Final Internative f) Source # | Since: 0.4.0.0 |
Defined in Data.HFunctor.Final | |
| Inplus (Final Inplus f) Source # | Since: 0.4.0.0 |
| Inalt (Final Inplus f) Source # | Since: 0.4.0.0 |
| Inplus (Chain Night Not f) Source # | Since: 0.4.0.0 |
class (Inplus f, Inplicative f) => Internative f Source #
The invariant counterpart to Alternative and Decidable: represents
a combination of both Applicative and Alt, or Divisible and
Conclude. There are laws?
Instances
Assembling Helpers
concatInplus :: Inplus f => NP f as -> f (NS I as) Source #
Convenient wrapper to build up an Inplus instance on by providing
each branch 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 = MTI Int | MTB Bool | MTS String
and an invariant functor and Inplus 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 (case MTI x -> Z (I x); MTB y -> S (Z (I y)); MTS z -> S (S (Z (I z))))
(case Z (I x) -> MTI x; S (Z (I y)) -> MTB y; S (S (Z (I z))) -> MTS z) $
concatInplus $ intPrim
:* boolPrim
:* stringPrim
:* Nil
Some notes on usefulness depending on how many components you have:
concatInalt :: Inalt f => NP f (a ': as) -> f (NS I (a ': as)) Source #
A version of concatInplus for non-empty NP, but only
requiring an Inalt instance.
Since: 0.4.0.0