functor-combinators-0.3.4.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.Chain

Description

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

Since: 0.3.0.0

Synopsis

Chain

newtype DayChain f a 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.

Constructors

DayChain 

Fields

Bundled Patterns

pattern Gather :: (a -> (b, c)) -> (b -> c -> a) -> f b -> DayChain f c -> DayChain f a

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

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

Instances

Instances details
Invariant (DayChain f) Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

invmap :: (a -> b) -> (b -> a) -> DayChain f a -> DayChain f b #

Inject DayChain Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

inject :: forall (f :: k -> Type). f ~> DayChain f Source #

HFunctor DayChain Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

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

gather :: (a -> (b, c)) -> (b -> c -> a) -> DayChain f b -> DayChain f c -> DayChain f a Source #

Invariantly combine two DayChains.

Analogous to liftA2 and divise. If there was some typeclass that represented semigroups on invariant Day, this would be the method of that typeclass.

The identity of this is Knot.

Since: 0.3.4.0

gathered :: DayChain f a -> DayChain f b -> DayChain f (a, b) Source #

Convenient wrapper over gather that simply combines the two options in a tuple. Analogous to divised.

Since: 0.3.4.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

newtype DayChain1 f a 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.

Constructors

DayChain1_ 

Fields

Bundled Patterns

pattern DayChain1 :: Invariant f => (a -> (b, c)) -> (b -> c -> a) -> f b -> DayChain f c -> DayChain1 f a

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

Instances

Instances details
Invariant f => Invariant (DayChain1 f) Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

invmap :: (a -> b) -> (b -> a) -> DayChain1 f a -> DayChain1 f b #

Inject DayChain1 Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

inject :: forall (f :: k -> Type). f ~> DayChain1 f Source #

HFunctor DayChain1 Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

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

gather1 :: Invariant f => (a -> (b, c)) -> (b -> c -> a) -> DayChain1 f b -> DayChain1 f c -> DayChain1 f a Source #

Invariantly combine two DayChain1s.

Analogous to liftA2 and divise. If there was some typeclass that represented semigroups on invariant Day, this would be the method of that typeclass.

Since: 0.3.4.0

gathered1 :: Invariant f => DayChain1 f a -> DayChain1 f b -> DayChain1 f (a, b) Source #

Convenient wrapper over gather1 that simply combines the two options in a tuple. Analogous to divised.

Since: 0.3.4.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.

Day Utility

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.