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

Data.Functor.Invariant.Inplicative.Free

Description

Provide an invariant functor combinator sequencer, like a combination of Ap and Div.

This module was named DecAlt before v0.4.0.0

Since: 0.4.0.0

Synopsis

Chain

newtype DivAp f a Source #

The invariant version of Ap and Div: combines the capabilities of both Ap and Div together.

Conceptually you can think of DivAp f a as a way of consuming and producing as that contains a collection of f xs of different xs. When interpreting this, each a is distributed across all f xs to each interpret, and then re-combined again to produce the resulting a.

To do this, the main tools to combine DivAps are its Inply instance, using gather to combine two DivAps in a choice-like manner (with the splitting and re-combining function), and its Inplicative instance, using knot to create an "empty" branch that does not contribute to the structure.

This does have an Interpret function, but the target typeclass (Inplicative) doesn't have too many useful instances. Instead, you are probably going to run it into either Applicative instance (to "produce" an a from a DivAp f a) with runCoDivAp, or a Divisible instance (to "consume" an a from a DivAp f a) with runContraDivAp.

If you think of this type as a combination of Ap and Div, then you can also extract the Ap part out using divApAp, and extract the Div part out using divApDiv.

Note that this type's utility is similar to that of PreT Ap, except PreT Ap lets you use Applicative typeclass methods to assemble it.

Since: 0.3.5.0

Constructors

DivAp 

Fields

Bundled Patterns

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

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

Note that the order of the first two arguments has swapped as of v0.4.0.0

pattern Knot :: a -> DivAp f a

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

Instances

Instances details
Inject DivAp Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

FreeOf Inplicative DivAp Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Associated Types

type FreeFunctorBy DivAp :: (Type -> Type) -> Constraint Source #

Methods

fromFree :: forall (f :: Type -> Type). DivAp f ~> Final Inplicative f Source #

toFree :: forall (f :: Type -> Type). FreeFunctorBy DivAp f => Final Inplicative f ~> DivAp f Source #

HTraversable DivAp Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

htraverse :: forall h f g (a :: k1). Applicative h => (forall (x :: k). f x -> h (g x)) -> DivAp f a -> h (DivAp g a) Source #

HFunctor DivAp Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

Inplicative f => Interpret DivAp (f :: Type -> Type) Source #

A free Inplicative

Instance details

Defined in Data.Functor.Invariant.Inplicative.Free

Methods

retract :: DivAp f ~> f Source #

interpret :: forall (g :: k -> Type). (g ~> f) -> DivAp g ~> f Source #

Inplicative (DivAp f) Source #

The free Inplicative

Instance details

Defined in Data.Functor.Invariant.Inplicative.Free

Methods

knot :: a -> DivAp f a Source #

Inply (DivAp f) Source # 
Instance details

Defined in Data.Functor.Invariant.Inplicative.Free

Methods

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

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

Invariant (DivAp f) Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

type FreeFunctorBy DivAp Source # 
Instance details

Defined in Data.HFunctor.Final

runCoDivAp :: forall f g. Applicative g => (f ~> g) -> DivAp f ~> g Source #

In the covariant direction, we can interpret into any Applicative.

In theory, this shouldn't never be necessary, because you should just be able to use interpret, since any instance of Applicative is also an instance of Inplicative. However, this can be handy if you are using an instance of Applicative that has no Inplicative instance. Consider also unsafeInplicativeCo if you are using a specific, concrete type for g.

runContraDivAp :: forall f g. Divisible g => (f ~> g) -> DivAp f ~> g Source #

In the covariant direction, we can interpret into any Divisible.

In theory, this shouldn't never be necessary, because you should just be able to use interpret, since any instance of Divisible is also an instance of Inplicative. However, this can be handy if you are using an instance of Divisible that has no Inplicative instance. Consider also unsafeInplicativeContra if you are using a specific, concrete type for g.

divApAp :: DivAp f ~> Ap f Source #

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

Since: 0.3.2.0

divApDiv :: DivAp f ~> Div f Source #

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

Since: 0.3.2.0

foldDivAp :: (forall x. x -> g x) -> (Day f g ~> g) -> DivAp f ~> g Source #

General-purpose folder of DivAp. Provide a way to handle the identity (pureconquerKnot) and a way to handle a cons (liftA2divideGather).

Since: 0.3.5.0

assembleDivAp :: NP f as -> DivAp f (NP I as) Source #

Convenient wrapper to build up a DivAp 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) $
  assembleDivAp $ 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.

If each component is itself a DivAp f (instead of f), you can use concatInplicative.

assembleDivApRec :: Rec f as -> DivAp f (XRec Identity as) Source #

A version of assembleDivAp 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) $
  assembleDivApRec $ intPrim
                     :& boolPrim
                     :& stringPrim
                     :& Nil

If each component is itself a DivAp f (instead of f), you can use concatDivApRec.

Nonempty Chain

newtype DivAp1 f a Source #

The invariant version of Ap1 and Div1: combines the capabilities of both Ap1 and Div1 together.

Conceptually you can think of DivAp1 f a as a way of consuming and producing as that contains a (non-empty) collection of f xs of different xs. When interpreting this, each a is distributed across all f xs to each interpret, and then re-combined again to produce the resulting a.

To do this, the main tools to combine DivAp1s are its Inply instance, using gather to combine two DivAp1s in a parallel-fork-like manner (with the splitting and re-combining function).

This does have an Interpret function, but the target typeclass (Inply) doesn't have too many useful instances. Instead, you are probably going to run it into either Apply instance (to "produce" an a from a DivAp1 f a) with runCoDivAp1, or a Divise instance (to "consume" an a from a DivAp1 f a) with runContraDivAp1.

If you think of this type as a combination of Ap1 and Div1, then you can also extract the Ap1 part out using divApAp1, and extract the Div1 part out using divApDiv1.

Note that this type's utility is similar to that of PreT Ap1, except PreT Ap1 lets you use Apply typeclass methods to assemble it.

Since: 0.3.5.0

Constructors

DivAp1_ 

Fields

Bundled Patterns

pattern DivAp1 :: Invariant f => (b -> c -> a) -> (a -> (b, c)) -> f b -> DivAp f c -> DivAp1 f a

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

Note that the order of the first two arguments has swapped as of v0.4.0.0

Instances

Instances details
Inject DivAp1 Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

FreeOf Inply DivAp1 Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Associated Types

type FreeFunctorBy DivAp1 :: (Type -> Type) -> Constraint Source #

Methods

fromFree :: forall (f :: Type -> Type). DivAp1 f ~> Final Inply f Source #

toFree :: forall (f :: Type -> Type). FreeFunctorBy DivAp1 f => Final Inply f ~> DivAp1 f Source #

HTraversable DivAp1 Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

htraverse :: forall h f g (a :: k1). Applicative h => (forall (x :: k). f x -> h (g x)) -> DivAp1 f a -> h (DivAp1 g a) Source #

HTraversable1 DivAp1 Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

htraverse1 :: forall h f g (a :: k1). Apply h => (forall (x :: k). f x -> h (g x)) -> DivAp1 f a -> h (DivAp1 g a) Source #

HFunctor DivAp1 Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

Inply f => Interpret DivAp1 (f :: Type -> Type) Source #

A free Inply

Instance details

Defined in Data.Functor.Invariant.Inplicative.Free

Methods

retract :: DivAp1 f ~> f Source #

interpret :: forall (g :: k -> Type). (g ~> f) -> DivAp1 g ~> f Source #

Invariant f => Inply (DivAp1 f) Source #

The free Inplicative

Instance details

Defined in Data.Functor.Invariant.Inplicative.Free

Methods

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

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

Invariant f => Invariant (DivAp1 f) Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

type FreeFunctorBy DivAp1 Source # 
Instance details

Defined in Data.HFunctor.Final

runCoDivAp1 :: forall f g. Apply g => (f ~> g) -> DivAp1 f ~> g Source #

In the covariant direction, we can interpret into any Apply.

In theory, this shouldn't never be necessary, because you should just be able to use interpret, since any instance of Apply is also an instance of Inply. However, this can be handy if you are using an instance of Apply that has no Inply instance. Consider also unsafeInplyCo if you are using a specific, concrete type for g.

runContraDivAp1 :: forall f g. Divise g => (f ~> g) -> DivAp1 f ~> g Source #

In the contravariant direction, we can interpret into any Divise.

In theory, this shouldn't never be necessary, because you should just be able to use interpret, since any instance of Divise is also an instance of Inply. However, this can be handy if you are using an instance of Divise that has no Inply instance. Consider also unsafeInplyContra if you are using a specific, concrete type for g.

divApAp1 :: DivAp1 f ~> Ap1 f Source #

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

Since: 0.3.2.0

divApDiv1 :: DivAp1 f ~> Div1 f Source #

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

Since: 0.3.2.0

foldDivAp1 :: (f ~> g) -> (Day f g ~> g) -> DivAp1 f ~> g Source #

General-purpose folder of DivAp1. Provide a way to handle the individual leaves and a way to handle a cons ('liftF2diviseGather).

Since: 0.3.5.0

assembleDivAp1 :: Invariant f => NP f (a ': as) -> DivAp1 f (NP I (a ': as)) Source #

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

If each component is itself a DivAp1 f (instead of f), you can use concatInply.

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

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

If each component is itself a DivAp1 f (instead of f), you can use concatDivAp1Rec.

Orphan instances

Inplicative f => Interpret DivAp (f :: Type -> Type) Source #

A free Inplicative

Instance details

Methods

retract :: DivAp f ~> f Source #

interpret :: forall (g :: k -> Type). (g ~> f) -> DivAp g ~> f Source #

Inply f => Interpret DivAp1 (f :: Type -> Type) Source #

A free Inply

Instance details

Methods

retract :: DivAp1 f ~> f Source #

interpret :: forall (g :: k -> Type). (g ~> f) -> DivAp1 g ~> f Source #

Inplicative (DivAp f) Source #

The free Inplicative

Instance details

Methods

knot :: a -> DivAp f a Source #

Inply (DivAp f) Source # 
Instance details

Methods

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

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

Invariant f => Inply (DivAp1 f) Source #

The free Inplicative

Instance details

Methods

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

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