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.Day

Description

Provides an Invariant version of the typical Haskell Day convolution over tuples.

Since: 0.3.0.0

Synopsis

Documentation

data Day :: (Type -> Type) -> (Type -> Type) -> Type -> Type where Source #

A pairing of invariant functors to create a new invariant functor that represents the "combination" between the two.

A Day f g a is a invariant "consumer" and "producer" of a, and it does this by taking the a and feeding it to both f and g, and aggregating back the results.

For example, if we have x :: f a and y :: g b, then day x y :: Day f g (a, b). This is a consumer/producer of (a, b)s, and it feeds the a to x and the b to y, and tuples the results back together.

Mathematically, this is a invariant day convolution along a tuple.

Constructors

Day :: f b -> g c -> (a -> (b, c)) -> (b -> c -> a) -> Day f g a 

Instances

Instances details
Associative Day Source # 
Instance details

Defined in Data.Functor.Invariant.Day

Associated Types

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

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

Methods

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

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

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

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

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

HBifunctor Day Source # 
Instance details

Defined in Data.Functor.Invariant.Day

Methods

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

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

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

Matchable Day Identity Source # 
Instance details

Defined in Data.Functor.Invariant.Day

Methods

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

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

Tensor Day Identity Source # 
Instance details

Defined in Data.Functor.Invariant.Day

Associated Types

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

Methods

intro1 :: forall (f :: Type -> Type). f ~> Day f Identity Source #

intro2 :: forall (g :: Type -> Type). g ~> Day Identity g Source #

elim1 :: forall (f :: Type -> Type). FunctorBy Day f => Day f Identity ~> f Source #

elim2 :: forall (g :: Type -> Type). FunctorBy Day g => Day Identity g ~> g Source #

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

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

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

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

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

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

Defined in Data.Functor.Invariant.Day

Methods

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

Invariant (Day f g) Source # 
Instance details

Defined in Data.Functor.Invariant.Day

Methods

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

type NonEmptyBy Day Source # 
Instance details

Defined in Data.Functor.Invariant.Day

type FunctorBy Day Source # 
Instance details

Defined in Data.Functor.Invariant.Day

type ListBy Day Source # 
Instance details

Defined in Data.Functor.Invariant.Day

day :: f a -> g b -> Day f g (a, b) Source #

Pair two invariant actions together in a way that tuples together their input/outputs. The first one will take the fst part of the tuple, and the second one will take the snd part of the tuple.

runDayApply :: forall f g h. Apply h => (f ~> h) -> (g ~> h) -> Day f g ~> h Source #

Interpret the covariant part of a Day into a target context h, as long as the context is an instance of Apply. The Apply is used to combine results back together using <*>.

runDayDivise :: forall f g h. Divise h => (f ~> h) -> (g ~> h) -> Day f g ~> h Source #

Interpret the contravariant part of a Day into a target context h, as long as the context is an instance of Divise. The Divise is used to split up the input to pass to each of the actions.

toCoDay :: Day f g ~> Day f g Source #

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

toContraDay :: Day f g ~> Day f g Source #

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

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

Day is associative.

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

Day is associative.

intro1 :: g ~> Day Identity g Source #

The left identity of Day is Identity; this is one side of that isomorphism.

intro2 :: f ~> Day f Identity Source #

The right identity of Day is Identity; this is one side of that isomorphism.

elim1 :: Invariant g => Day Identity g ~> g Source #

The left identity of Day is Identity; this is one side of that isomorphism.

elim2 :: Invariant f => Day f Identity ~> f Source #

The right identity of Day is Identity; this is one side of that isomorphism.

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

The two sides of a Day can be swapped.

trans1 :: (f ~> h) -> Day f g ~> Day h g Source #

Hoist a function over the left side of a Day.

trans2 :: (g ~> h) -> Day f g ~> Day f h Source #

Hoist a function over the right side of a Day.

Chain

type DayChain = Chain Day Identity 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 runCoDayChain and runContraDayChain. There is no general invariant interpreter (and so no MonoidIn instance for Day) 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 Gather :: (a -> (b, c)) -> (b -> c -> a) -> f b -> DayChain f c -> DayChain f a Source #

Match on a non-empty DayChain; contains no fs, but only the terminal value. Analogous to the Ap constructor.

pattern Knot :: a -> DayChain f a Source #

Match on an "empty" DayChain; contains no fs, but only the terminal value. Analogous to Pure.

runCoDayChain :: forall f g. Applicative g => (f ~> g) -> DayChain f ~> g Source #

In the covariant direction, we can interpret out of a Chain of Day into any Applicative.

runContraDayChain :: forall f g. Divisible g => (f ~> g) -> DayChain f ~> g Source #

In the contravariant direction, we can interpret out of a Chain of Day into any Divisible.

chainAp :: DayChain f ~> Ap f Source #

Extract the Ap part out of a DayChain, shedding the contravariant bits.

Since: 0.3.2.0

chainDiv :: DayChain f ~> Div f Source #

Extract the Div part out of a DayChain, shedding the covariant bits.

Since: 0.3.2.0

assembleDayChain :: NP f as -> DayChain f (NP I as) Source #

Convenient wrapper to build up a DayChain 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 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) $
  assembleDayChain $ 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 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 tuples one-by-one.

assembleDayChainRec :: Rec f as -> DayChain f (XRec Identity as) Source #

A version of assembleDayChain 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.

data MyType = MT Int Bool String

invmap ((MyType x y z) -> x ::& y ::& z ::& RNil)
       ((x ::& y ::& z ::& RNil) -> MyType x y z) $
  assembleDayChainRec $ intPrim
                     :& boolPrim
                     :& stringPrim
                     :& Nil

concatDayChain :: NP (DayChain f) as -> DayChain f (NP I as) Source #

A version of assembleDayChain where each component is itself a DayChain.

assembleDayChain (x :* y :* z :* Nil)
  = concatDayChain (injectChain x :* injectChain y :* injectChain z :* Nil)

concatDayChainRec :: Rec (DayChain f) as -> DayChain f (XRec Identity as) Source #

A version of concatDayChain 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.

Nonempty Chain

type DayChain1 = Chain1 Day 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 runCoDayChain1 and runContraDayChain1. There is no general invariant interpreter (and so no SemigroupIn instance for Day) 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 DayChain1 :: Invariant f => (a -> (b, c)) -> (b -> c -> a) -> f b -> DayChain f c -> DayChain1 f a Source #

Match on a DayChain1 to get the head and the rest of the items. Analogous to the Ap1 constructor.

runCoDayChain1 :: forall f g. Apply g => (f ~> g) -> DayChain1 f ~> g Source #

In the covariant direction, we can interpret out of a Chain1 of Day into any Apply.

runContraDayChain1 :: forall f g. Divise g => (f ~> g) -> DayChain1 f ~> g Source #

In the contravariant direction, we can interpret out of a Chain1 of Day into any Divise.

chainAp1 :: DayChain1 f ~> Ap1 f Source #

Extract the Ap1 part out of a DayChain1, shedding the contravariant bits.

Since: 0.3.2.0

chainDiv1 :: DayChain1 f ~> Div1 f Source #

Extract the Div1 part out of a DayChain1, shedding the covariant bits.

Since: 0.3.2.0

assembleDayChain1 :: Invariant f => NP f (a ': as) -> DayChain1 f (NP I (a ': as)) Source #

A version of assembleDayChain but for DayChain1 instead. Can be useful if you intend on interpreting it into something with only a Divise or Apply instance, but no Divisible or Applicative.

assembleDayChain1Rec :: Invariant f => Rec f (a ': as) -> DayChain1 f (XRec Identity (a ': as)) Source #

A version of assembleDayChain1 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.

concatDayChain1 :: Invariant f => NP (DayChain1 f) (a ': as) -> DayChain1 f (NP I (a ': as)) Source #

A version of concatDayChain but for DayChain1 instead. Can be useful if you intend on interpreting it into something with only a Divise or Apply instance, but no Divisible or Applicative.

concatDayChain1Rec :: Invariant f => Rec (DayChain1 f) (a ': as) -> DayChain1 f (XRec Identity (a ': as)) Source #

A version of concatDayChain1 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.