| Copyright | (c) Justin Le 2019 |
|---|---|
| License | BSD3 |
| Maintainer | [email protected] |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.Functor.Invariant.Night
Contents
Synopsis
- data Night :: (Type -> Type) -> (Type -> Type) -> Type -> Type where
- newtype Not a = Not {}
- night :: f a -> g b -> Night f g (Either a b)
- runNightAlt :: forall f g h. Alt h => (f ~> h) -> (g ~> h) -> Night f g ~> h
- runNightDecide :: forall f g h. Decide h => (f ~> h) -> (g ~> h) -> Night f g ~> h
- toCoNight :: (Functor f, Functor g) => Night f g ~> (f :*: g)
- toContraNight :: Night f g ~> Night f g
- assoc :: Night f (Night g h) ~> Night (Night f g) h
- unassoc :: Night (Night f g) h ~> Night f (Night g h)
- intro1 :: g ~> Night Not g
- intro2 :: f ~> Night f Not
- elim1 :: Invariant g => Night Not g ~> g
- elim2 :: Invariant f => Night f Not ~> f
- swapped :: Night f g ~> Night g f
- trans1 :: (f ~> h) -> Night f g ~> Night h g
- trans2 :: (g ~> h) -> Night f g ~> Night f h
- type NightChain = Chain Night Not
- pattern Share :: (a -> Either b c) -> (b -> a) -> (c -> a) -> f b -> NightChain f c -> NightChain f a
- pattern Reject :: (a -> Void) -> NightChain f a
- runCoNightChain :: forall f g. Plus g => (f ~> g) -> NightChain f ~> g
- runContraNightChain :: forall f g. Conclude g => (f ~> g) -> NightChain f ~> g
- assembleNightChain :: NP f as -> NightChain f (NS I as)
- concatNightChain :: NP (NightChain f) as -> NightChain f (NS I as)
- type NightChain1 = Chain1 Night
- pattern NightChain1 :: Invariant f => (a -> Either b c) -> (b -> a) -> (c -> a) -> f b -> NightChain f c -> NightChain1 f a
- runCoNightChain1 :: forall f g. Alt g => (f ~> g) -> NightChain1 f ~> g
- runContraNightChain1 :: forall f g. Decide g => (f ~> g) -> NightChain1 f ~> g
- assembleNightChain1 :: Invariant f => NP f (a ': as) -> NightChain1 f (NS I (a ': as))
- concatNightChain1 :: Invariant f => NP (NightChain1 f) (a ': as) -> NightChain1 f (NS I (a ': as))
Documentation
data Night :: (Type -> Type) -> (Type -> Type) -> Type -> Type where Source #
A pairing of invariant functors to create a new invariant functor that represents the "choice" between the two.
A is a invariant "consumer" and "producer" of Night f g aa, and
it does this by either feeding the a to f, or feeding the a to
g, and then collecting the result from whichever one it was fed to.
Which decision of which path to takes happens at runtime depending
what a is actually given.
For example, if we have x :: f a and y :: g b, then . This is a consumer/producer of night x y ::
Night f g (Either a b)s, and
it consumes Either a bLeft branches by feeding it to x, and Right branches
by feeding it to y. It then passes back the single result from the one of
the two that was chosen.
Mathematically, this is a invariant day convolution, except with
a different choice of bifunctor (Either) than the typical one we talk
about in Haskell (which uses (,)). Therefore, it is an alternative to
the typical Day convolution --- hence, the name Night.
Instances
A value of type is "proof" that Not aa is uninhabited.
Instances
toContraNight :: Night f g ~> Night f g Source #
Convert an invariant Night into the contravariant version, dropping
the covariant part.
trans1 :: (f ~> h) -> Night f g ~> Night h g Source #
Hoist a function over the left side of a Night.
trans2 :: (g ~> h) -> Night f g ~> Night f h Source #
Hoist a function over the right side of a Night.
Chain
type NightChain = Chain Night Not Source #
Instead of defining yet another separate free monoid like
Ap,
Div, or
Dec, we re-use Chain.
You can assemble values using the combinators in Data.HFunctor.Chain,
and then tear them down/interpret them using runCoNightChain and
runContraNightChain. There is no general invariant interpreter (and so no
MonoidIn instance for Night) because the typeclasses used to express
the target contexts are probably not worth defining given how little the
Haskell ecosystem uses invariant functors as an abstraction.
pattern Share :: (a -> Either b c) -> (b -> a) -> (c -> a) -> f b -> NightChain f c -> NightChain f a Source #
Match on a non-empty NightChain; contains no fs, but only the
terminal value. Analogous to the
Choose constructor.
pattern Reject :: (a -> Void) -> NightChain f a Source #
Match on an "empty" NightChain; contains no fs, but only the
terminal value. Analogous to the
Lose constructor.
runCoNightChain :: forall f g. Plus g => (f ~> g) -> NightChain f ~> g Source #
runContraNightChain :: forall f g. Conclude g => (f ~> g) -> NightChain f ~> g Source #
assembleNightChain :: NP f as -> NightChain f (NS I as) Source #
Convenient wrapper to build up a NightChain on 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 = MTI Int | MTB Bool | MTS 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 (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) $
assembleNightChain $ intPrim
:* boolPrim
:* stringPrim
:* Nil
This is much more convenient than doing it using manual applications of
decide or choose or Night,
which would require manually peeling off eithers one-by-one.
concatNightChain :: NP (NightChain f) as -> NightChain f (NS I as) Source #
A version of assembleNightChain where each component is itself
a NightChain.
assembleNightChain (x :* y :* z :* Nil) = concatNightChain (injectChain x :* injectChain y :* injectChain z :* Nil)
Nonempty Chain
type NightChain1 = Chain1 Night Source #
Instead of defining yet another separate free semigroup like
Ap1,
Div1, or
Dec1, we re-use Chain1.
You can assemble values using the combinators in Data.HFunctor.Chain,
and then tear them down/interpret them using runCoNightChain1 and
runContraNightChain1. There is no general invariant interpreter (and so no
SemigroupIn instance for Night) because the typeclasses used to
express the target contexts are probably not worth defining given how
little the Haskell ecosystem uses invariant functors as an abstraction.
pattern NightChain1 :: Invariant f => (a -> Either b c) -> (b -> a) -> (c -> a) -> f b -> NightChain f c -> NightChain1 f a Source #
Match on a NightChain1 to get the head and the rest of the items.
Analogous to the Dec1
constructor.
runCoNightChain1 :: forall f g. Alt g => (f ~> g) -> NightChain1 f ~> g Source #
runContraNightChain1 :: forall f g. Decide g => (f ~> g) -> NightChain1 f ~> g Source #
assembleNightChain1 :: Invariant f => NP f (a ': as) -> NightChain1 f (NS I (a ': as)) Source #
A version of assembleNightChain but for NightChain1 instead. Can
be useful if you intend on interpreting it into something with only
a Decide or Alt instance, but no
Decidable or Plus or
Alternative.
concatNightChain1 :: Invariant f => NP (NightChain1 f) (a ': as) -> NightChain1 f (NS I (a ': as)) Source #
A version of concatNightChain but for NightChain1 instead. Can be
useful if you intend on interpreting it into something with only
a Decide or Alt instance, but no Decidable or Plus or
Alternative.