functor-combinators-0.3.5.1: 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.DecAlt

Description

Provide an invariant functor combinator choice-collector, like a combination of ListF and Dec.

Since: 0.3.5.0

Synopsis

Chain

newtype DecAlt f a Source #

The invariant version of ListF and Dec: combines the capabilities of both ListF and Dec together.

Conceptually you can think of DecAlt f a as a way of consuming and producing as that contains a collection of f xs of different xs. When interpreting this, a specific f is chosen to handle the interpreting; the a is sent to that f, and the single result is returned back out.

You run this in any Plus context if you want to interpret it covariantly, treating DecAlt f a as a producer of a, using runCoDecAlt. You can run this in any Conclude context if you you want to interpret it contravariantly, treating DecAlt f a as a consumer of as, using runContraDecAlt.

Because there is no typeclass that combines both Plus and Conclude, this type is a little bit tricker to construct/use than ListF or Dec.

  • Instead of <!> and decide (typeclass methods), use swerve and other variants, which work specifically on this type only.
  • Instead of empty and conclude (typeclass methods), use Reject.
  • Instead of using interpret (to run in a typeclass), either use runCoDecAlt (to run in Plus), runContraDecAlt (to run in Conclude), or foldDecAlt (to interpret by manually providing handlers)

You can also extract the ListF part out using decAltListF, and extract the Dec part out using decAltDec.

Note that this type's utility is similar to that of PostT Dec, except PostT Dec lets you use Conclude typeclass methods to assemble it.

Since: 0.3.5.0

Constructors

DecAlt 

Fields

Bundled Patterns

pattern Swerve :: (a -> Either b c) -> (b -> a) -> (c -> a) -> f b -> DecAlt f c -> DecAlt f a

Match on a non-empty DecAlt; 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) -> DecAlt f a

Match on an "empty" DecAlt; contains no fs, but only the terminal value. Analogous to the Lose constructor.

Instances

Instances details
Inject DecAlt Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

Invariant (DecAlt f) Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

HFunctor DecAlt Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

runCoDecAlt :: forall f g. Plus g => (f ~> g) -> DecAlt f ~> g Source #

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

runContraDecAlt :: forall f g. Conclude g => (f ~> g) -> DecAlt f ~> g Source #

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

decAltListF :: Functor f => DecAlt f ~> ListF f Source #

Extract the ListF part out of a DecAlt, shedding the contravariant bits.

Since: 0.3.2.0

decAltListF_ :: DecAlt f ~> ComposeT ListF Coyoneda f Source #

Extract the ListF part out of a DecAlt, 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

decAltDec :: DecAlt f ~> Dec f Source #

Extract the Dec part out of a DecAlt, shedding the covariant bits.

foldDecAlt :: (forall x. (x -> Void) -> g x) -> (Night f g ~> g) -> DecAlt f ~> g Source #

General-purpose folder of DecAlt. Provide a way to handle the identity (emptyconcludeReject) and a way to handle a cons (<!>decideswerve).

Since: 0.3.5.0

swerve :: (a -> Either b c) -> (b -> a) -> (c -> a) -> DecAlt f b -> DecAlt f c -> DecAlt f a Source #

Invariantly combine two DecAlts.

Analogous to <|> and decide. If there was some typeclass that represented semigroups on invariant Night, this would be the method of that typeclass.

The identity of this is Reject.

Since: 0.3.4.0

swerved :: DecAlt f a -> DecAlt f b -> DecAlt f (Either a b) Source #

Convenient wrapper over swerve that simply combines the two options in an Either. Analogous to <|> and decided.

Since: 0.3.4.0

assembleDecAlt :: NP f as -> DecAlt f (NS I as) Source #

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

concatDecAlt :: NP (DecAlt f) as -> DecAlt f (NS I as) Source #

A version of assembleDecAlt where each component is itself a DecAlt.

assembleDecAlt (x :* y :* z :* Nil)
  = concatDecAlt (injectChain x :* injectChain y :* injectChain z :* Nil)

Nonempty Chain

newtype DecAlt1 f a Source #

The invariant version of NonEmptyF and Dec1: combines the capabilities of both NonEmptyF and Dec1 together.

Conceptually you can think of DecAlt1 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, a specific f is chosen to handle the interpreting; the a is sent to that f, and the single result is returned back out.

You run this in any Alt context if you want to interpret it covariantly, treating DecAlt1 f a as a producer of a, using runCoDecAlt1. You can run this in any Decide context if you you want to interpret it contravariantly, treating DecAlt1 f a as a consumer of as, using runContraDecAlt1.

Because there is no typeclass that combines both Alt and Decide, this type is a little bit tricker to construct/use than NonEmptyF or Dec1.

  • Instead of <!> and decide (typeclass methods), use swerve1 and other variants, which work specifically on this type only.
  • Instead of using interpret (to run in a typeclass), either use runCoDecAlt1 (to run in Alt), runContraDecAlt1 (to run in Decide), or foldDecAlt1 (to interpret by manually providing handlers)

You can also extract the NonEmptyF part out using decAltNonEmptyF, and extract the Dec1 part out using decAltDec1.

Note that this type's utility is similar to that of PostT Dec1, except PostT Dec1 lets you use Decide typeclass methods to assemble it.

Since: 0.3.5.0

Constructors

DecAlt1_ 

Fields

Bundled Patterns

pattern DecAlt1 :: Invariant f => (a -> Either b c) -> (b -> a) -> (c -> a) -> f b -> DecAlt f c -> DecAlt1 f a

Match on a DecAlt1 to get the head and the rest of the items. Analogous to the Dec1 constructor.

Instances

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

Defined in Data.HFunctor.Chain.Internal

Methods

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

Inject DecAlt1 Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

HFunctor DecAlt1 Source # 
Instance details

Defined in Data.HFunctor.Chain.Internal

Methods

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

runCoDecAlt1 :: forall f g. Alt g => (f ~> g) -> DecAlt1 f ~> g Source #

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

runContraDecAlt1 :: forall f g. Decide g => (f ~> g) -> DecAlt1 f ~> g Source #

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

decAltNonEmptyF :: Functor f => DecAlt1 f ~> NonEmptyF f Source #

Extract the NonEmptyF part out of a DecAlt1, shedding the contravariant bits.

Since: 0.3.2.0

decAltNonEmptyF_ :: DecAlt1 f ~> ComposeT NonEmptyF Coyoneda f Source #

Extract the NonEmptyF part out of a DecAlt1, 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

decAltDec1 :: DecAlt1 f ~> Dec1 f Source #

Extract the Dec1 part out of a DecAlt1, shedding the covariant bits.

foldDecAlt1 :: (f ~> g) -> (Night f g ~> g) -> DecAlt1 f ~> g Source #

General-purpose folder of DecAlt1. Provide a way to handle the individual leaves and a way to handle a cons (<!>decideswerve1).

Since: 0.3.5.0

swerve1 :: Invariant f => (a -> Either b c) -> (b -> a) -> (c -> a) -> DecAlt1 f b -> DecAlt1 f c -> DecAlt1 f a Source #

Invariantly combine two DecAlt1s.

Analogous to <|> and decide. If there was some typeclass that represented semigroups on invariant Night, this would be the method of that typeclass.

Since: 0.3.4.0

swerved1 :: Invariant f => DecAlt1 f a -> DecAlt1 f b -> DecAlt1 f (Either a b) Source #

Convenient wrapper over swerve1 that simply combines the two options in an Either. Analogous to <|> and decided.

Since: 0.3.4.0

assembleDecAlt1 :: Invariant f => NP f (a ': as) -> DecAlt1 f (NS I (a ': as)) Source #

A version of assembleDecAlt but for DecAlt1 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.

concatDecAlt1 :: Invariant f => NP (DecAlt1 f) (a ': as) -> DecAlt1 f (NS I (a ': as)) Source #

A version of concatDecAlt but for DecAlt1 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.