functor-combinators-0.3.2.0: Tools for functor combinator-based program design
Copyright(c) Justin Le 2019
LicenseBSD3
Maintainerjustin@jle.im
Stabilityexperimental
Portabilitynon-portable
Safe HaskellNone
LanguageHaskell2010

Data.Functor.Invariant.Night

Description

Provides an Invariant version of a Day convolution over Either.

Since: 0.3.0.0

Synopsis

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 Night f g a is a invariant "consumer" and "producer" of a, 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 night x y :: Night f g (Either a b). This is a consumer/producer of Either a bs, and it consumes Left 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.

Constructors

Night :: f b -> g c -> (a -> Either b c) -> (b -> a) -> (c -> a) -> Night f g a 

Instances

Instances details
Associative Night Source # 
Instance details

Defined in Data.Functor.Invariant.Night

Associated Types

type NonEmptyBy Night :: (Type -> Type) -> Type -> Type Source #

type FunctorBy Night :: (Type -> Type) -> Constraint Source #

Methods

associating :: forall (f :: Type -> Type) (g :: Type -> Type) (h :: Type -> Type). (FunctorBy Night f, FunctorBy Night g, FunctorBy Night h) => Night f (Night g h) <~> Night (Night f g) h Source #

appendNE :: forall (f :: Type -> Type). Night (NonEmptyBy Night f) (NonEmptyBy Night f) ~> NonEmptyBy Night f Source #

matchNE :: forall (f :: Type -> Type). FunctorBy Night f => NonEmptyBy Night f ~> (f :+: Night f (NonEmptyBy Night f)) Source #

consNE :: forall (f :: Type -> Type). Night f (NonEmptyBy Night f) ~> NonEmptyBy Night f Source #

toNonEmptyBy :: forall (f :: Type -> Type). Night f f ~> NonEmptyBy Night f Source #

HBifunctor Night Source # 
Instance details

Defined in Data.Functor.Invariant.Night

Methods

hleft :: forall (f :: k -> Type) (j :: k -> Type) (g :: k -> Type). (f ~> j) -> Night f g ~> Night j g Source #

hright :: forall (g :: k -> Type) (l :: k -> Type) (f :: k -> Type). (g ~> l) -> Night f g ~> Night f l Source #

hbimap :: forall (f :: k -> Type) (j :: k -> Type) (g :: k -> Type) (l :: k -> Type). (f ~> j) -> (g ~> l) -> Night f g ~> Night j l Source #

Matchable Night Not Source # 
Instance details

Defined in Data.Functor.Invariant.Night

Methods

unsplitNE :: forall (f :: Type -> Type). FunctorBy Night f => Night f (ListBy Night f) ~> NonEmptyBy Night f Source #

matchLB :: forall (f :: Type -> Type). FunctorBy Night f => ListBy Night f ~> (Not :+: NonEmptyBy Night f) Source #

Tensor Night Not Source # 
Instance details

Defined in Data.Functor.Invariant.Night

Associated Types

type ListBy Night :: (Type -> Type) -> Type -> Type Source #

Methods

intro1 :: forall (f :: Type -> Type). f ~> Night f Not Source #

intro2 :: forall (g :: Type -> Type). g ~> Night Not g Source #

elim1 :: forall (f :: Type -> Type). FunctorBy Night f => Night f Not ~> f Source #

elim2 :: forall (g :: Type -> Type). FunctorBy Night g => Night Not g ~> g Source #

appendLB :: forall (f :: Type -> Type). Night (ListBy Night f) (ListBy Night f) ~> ListBy Night f Source #

splitNE :: forall (f :: Type -> Type). NonEmptyBy Night f ~> Night f (ListBy Night f) Source #

splittingLB :: forall (f :: Type -> Type). ListBy Night f <~> (Not :+: Night f (ListBy Night f)) Source #

toListBy :: forall (f :: Type -> Type). Night f f ~> ListBy Night f Source #

fromNE :: forall (f :: Type -> Type). NonEmptyBy Night f ~> ListBy Night f Source #

HFunctor (Night f :: (Type -> Type) -> Type -> Type) Source # 
Instance details

Defined in Data.Functor.Invariant.Night

Methods

hmap :: forall (f0 :: k -> Type) (g :: k -> Type). (f0 ~> g) -> Night f f0 ~> Night f g Source #

Invariant (Night f g) Source # 
Instance details

Defined in Data.Functor.Invariant.Night

Methods

invmap :: (a -> b) -> (b -> a) -> Night f g a -> Night f g b #

type NonEmptyBy Night Source # 
Instance details

Defined in Data.Functor.Invariant.Night

type FunctorBy Night Source # 
Instance details

Defined in Data.Functor.Invariant.Night

type ListBy Night Source # 
Instance details

Defined in Data.Functor.Invariant.Night

newtype Not a Source #

A value of type Not a is "proof" that a is uninhabited.

Constructors

Not 

Fields

Instances

Instances details
Contravariant Not Source # 
Instance details

Defined in Data.Functor.Contravariant.Night

Methods

contramap :: (a -> b) -> Not b -> Not a #

(>$) :: b -> Not b -> Not a #

Invariant Not Source #

Since: 0.3.1.0

Instance details

Defined in Data.Functor.Contravariant.Night

Methods

invmap :: (a -> b) -> (b -> a) -> Not a -> Not b #

Matchable Night Not Source #

Since: 0.3.0.0

Instance details

Defined in Data.HBifunctor.Tensor

Methods

unsplitNE :: forall (f :: Type -> Type). FunctorBy Night f => Night f (ListBy Night f) ~> NonEmptyBy Night f Source #

matchLB :: forall (f :: Type -> Type). FunctorBy Night f => ListBy Night f ~> (Not :+: NonEmptyBy Night f) Source #

Matchable Night Not Source # 
Instance details

Defined in Data.Functor.Invariant.Night

Methods

unsplitNE :: forall (f :: Type -> Type). FunctorBy Night f => Night f (ListBy Night f) ~> NonEmptyBy Night f Source #

matchLB :: forall (f :: Type -> Type). FunctorBy Night f => ListBy Night f ~> (Not :+: NonEmptyBy Night f) Source #

Tensor Night Not Source #

Since: 0.3.0.0

Instance details

Defined in Data.HBifunctor.Tensor

Associated Types

type ListBy Night :: (Type -> Type) -> Type -> Type Source #

Methods

intro1 :: forall (f :: Type -> Type). f ~> Night f Not Source #

intro2 :: forall (g :: Type -> Type). g ~> Night Not g Source #

elim1 :: forall (f :: Type -> Type). FunctorBy Night f => Night f Not ~> f Source #

elim2 :: forall (g :: Type -> Type). FunctorBy Night g => Night Not g ~> g Source #

appendLB :: forall (f :: Type -> Type). Night (ListBy Night f) (ListBy Night f) ~> ListBy Night f Source #

splitNE :: forall (f :: Type -> Type). NonEmptyBy Night f ~> Night f (ListBy Night f) Source #

splittingLB :: forall (f :: Type -> Type). ListBy Night f <~> (Not :+: Night f (ListBy Night f)) Source #

toListBy :: forall (f :: Type -> Type). Night f f ~> ListBy Night f Source #

fromNE :: forall (f :: Type -> Type). NonEmptyBy Night f ~> ListBy Night f Source #

Tensor Night Not Source # 
Instance details

Defined in Data.Functor.Invariant.Night

Associated Types

type ListBy Night :: (Type -> Type) -> Type -> Type Source #

Methods

intro1 :: forall (f :: Type -> Type). f ~> Night f Not Source #

intro2 :: forall (g :: Type -> Type). g ~> Night Not g Source #

elim1 :: forall (f :: Type -> Type). FunctorBy Night f => Night f Not ~> f Source #

elim2 :: forall (g :: Type -> Type). FunctorBy Night g => Night Not g ~> g Source #

appendLB :: forall (f :: Type -> Type). Night (ListBy Night f) (ListBy Night f) ~> ListBy Night f Source #

splitNE :: forall (f :: Type -> Type). NonEmptyBy Night f ~> Night f (ListBy Night f) Source #

splittingLB :: forall (f :: Type -> Type). ListBy Night f <~> (Not :+: Night f (ListBy Night f)) Source #

toListBy :: forall (f :: Type -> Type). Night f f ~> ListBy Night f Source #

fromNE :: forall (f :: Type -> Type). NonEmptyBy Night f ~> ListBy Night f Source #

Conclude f => MonoidIn Night Not f Source #

Instances of Conclude are monoids in the monoidal category on Night.

Instance details

Defined in Data.HBifunctor.Tensor

Methods

pureT :: Not ~> f Source #

Semigroup (Not a) Source # 
Instance details

Defined in Data.Functor.Contravariant.Night

Methods

(<>) :: Not a -> Not a -> Not a #

sconcat :: NonEmpty (Not a) -> Not a #

stimes :: Integral b => b -> Not a -> Not a #

Decide (Chain Night Not f) Source #

Since: 0.3.0.0

Instance details

Defined in Data.HFunctor.Chain

Methods

decide :: (a -> Either b c) -> Chain Night Not f b -> Chain Night Not f c -> Chain Night Not f a Source #

Conclude (Chain Night Not f) Source #

Chain Night Refutec is the free "monoid in the monoidal category of endofunctors enriched by Night" --- aka, the free Conclude.

Since: 0.3.0.0

Instance details

Defined in Data.HFunctor.Chain

Methods

conclude :: (a -> Void) -> Chain Night Not f a Source #

refuted :: Not Void Source #

A useful shortcut for a common usage: Void is always not so.

Since: 0.3.1.0

night :: f a -> g b -> Night f g (Either a b) Source #

Pair two invariant actions together into a Night; assigns the first one to Left inputs and outputs and the second one to Right inputs and outputs.

runNightAlt :: forall f g h. Alt h => (f ~> h) -> (g ~> h) -> Night f g ~> h Source #

Interpret the covariant part of a Night into a target context h, as long as the context is an instance of Alt. The Alt is used to combine results back together, chosen by <!>.

runNightDecide :: forall f g h. Decide h => (f ~> h) -> (g ~> h) -> Night f g ~> h Source #

Interpret the contravariant part of a Night into a target context h, as long as the context is an instance of Decide. The Decide is used to pick which part to feed the input to.

toCoNight :: (Functor f, Functor g) => Night f g ~> (f :*: g) Source #

Convert an invariant Night into the covariant version, dropping the contravariant part.

Note that there is no covariant version of Night defined in any common library, so we use an equivalent type (if f and g are Functors) f :*: g.

toCoNight_ :: Night f g ~> (Coyoneda f :*: Coyoneda g) Source #

Convert an invariant Night into the covariant version, dropping the contravariant part.

This version does not require a Functor constraint because it converts to the coyoneda-wrapped product, which is more accurately the covariant Night convolution.

Since: 0.3.2.0

toContraNight :: Night f g ~> Night f g Source #

Convert an invariant Night into the contravariant version, dropping the covariant part.

assoc :: Night f (Night g h) ~> Night (Night f g) h Source #

Night is associative.

unassoc :: Night (Night f g) h ~> Night f (Night g h) Source #

Night is associative.

intro1 :: g ~> Night Not g Source #

The left identity of Night is Not; this is one side of that isomorphism.

intro2 :: f ~> Night f Not Source #

The right identity of Night is Not; this is one side of that isomorphism.

elim1 :: Invariant g => Night Not g ~> g Source #

The left identity of Night is Not; this is one side of that isomorphism.

elim2 :: Invariant f => Night f Not ~> f Source #

The right identity of Night is Not; this is one side of that isomorphism.

swapped :: Night f g ~> Night g f Source #

The two sides of a Night can be swapped.

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 fs, but only the terminal value. Analogous to the Lose constructor.

runCoNightChain :: forall f g. Plus g => (f ~> g) -> NightChain f ~> g Source #

In the covariant direction, we can interpret out of a Chain of Night into any Plus.

runContraNightChain :: forall f g. Conclude g => (f ~> g) -> NightChain f ~> g Source #

In the contravariant direction, we can interpret out of a Chain of Night into any Conclude.

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 or injectChain directly.
  • If you have 2 components, use toListBy or toChain.
  • 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 #

In the covariant direction, we can interpret out of a Chain1 of Night into any Alt.

runContraNightChain1 :: forall f g. Decide g => (f ~> g) -> NightChain1 f ~> g Source #

In the contravariant direction, we can interpret out of a Chain1 of Night into any Decide.

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.