Copyright | (c) Justin Le 2019 |
---|---|
License | BSD3 |
Maintainer | justin@jle.im |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
Synopsis
- data Night :: (Type -> Type) -> (Type -> Type) -> Type -> Type where
- newtype Not a = Not {}
- refuted :: Not Void
- 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)
- toCoNight_ :: Night f g ~> (Coyoneda f :*: Coyoneda 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 Swerve :: (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
- chainListF :: Functor f => NightChain f ~> ListF f
- chainListF_ :: NightChain f ~> ComposeT ListF Coyoneda f
- chainDec :: NightChain f ~> Dec f
- 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
- chainNonEmptyF :: Functor f => NightChain1 f ~> NonEmptyF f
- chainNonEmptyF_ :: NightChain1 f ~> ComposeT NonEmptyF Coyoneda f
- chainDec1 :: NightChain1 f ~> Dec1 f
- 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
A useful shortcut for a common usage: Void
is always not so.
Since: 0.3.1.0
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 Swerve :: (a -> Either b c) -> (b -> a) -> (c -> a) -> f b -> NightChain f c -> NightChain f a Source #
Match on a non-empty NightChain
; contains the splitting function,
the two rejoining functions, the first f
, and the rest of the chain.
Analogous to the Choose
constructor.
pattern Reject :: (a -> Void) -> NightChain f a Source #
Match on an "empty" NightChain
; contains no f
s, 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 #
chainListF :: Functor f => NightChain f ~> ListF f Source #
Extract the ListF
part out of a NightChain
, shedding the
contravariant bits.
Since: 0.3.2.0
chainListF_ :: NightChain f ~> ComposeT ListF Coyoneda f Source #
Extract the ListF
part out of a NightChain
, shedding the
contravariant bits.
This version does not require a Functor
constraint because it converts
to the coyoneda-wrapped product, which is more accurately the true
conversion to a covariant chain.
Since: 0.3.2.0
chainDec :: NightChain f ~> Dec f Source #
Extract the Dec
part out of a NightChain
, shedding the
covariant bits.
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
Some notes on usefulness depending on how many components you have:
- If you have 0 components, use
Reject
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 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 #
chainNonEmptyF :: Functor f => NightChain1 f ~> NonEmptyF f Source #
Extract the NonEmptyF
part out of a NightChain1
, shedding the
contravariant bits.
Since: 0.3.2.0
chainNonEmptyF_ :: NightChain1 f ~> ComposeT NonEmptyF Coyoneda f Source #
Extract the NonEmptyF
part out of a NightChain1
, shedding the
contravariant bits.
This version does not require a Functor
constraint because it converts
to the coyoneda-wrapped product, which is more accurately the true
conversion to a covariant chain.
Since: 0.3.2.0
chainDec1 :: NightChain1 f ~> Dec1 f Source #
Extract the Dec1
part out of a NightChain1
, shedding the
covariant bits.
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
.