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

Data.Functor.Invariant.Internative

Description

Contains the classes Inalt and Inplus, the invariant counterparts to AltPlus and DecideConclude and Alternative/Decidable.

Since: 0.4.0.0

Synopsis

Typeclass

class Invariant f => Inalt f where Source #

The invariant counterpart of Alt and Decide.

Conceptually you can think of Alt as, given a way to "inject" a and b as c, lets you merge f a (producer of a) and f b (producer of b) into a f c (producer of c), in an "either-or" fashion. Decide can be thought of as, given a way to "discriminate" a c as either a a or a b, lets you merge f a (consumer of a) and f b (consumder of b) into a f c (consumer of c) in an "either-or" forking fashion (split the c into a or b, and use the appropriate handler).

Inalt, for swerve, requires both an injecting function and a choosing function in order to merge f b (producer and consumer of b) and f c (producer and consumer of c) into a f a in an either-or manner. You can think of it as, for the f a, it "chooses" if the a is actually a b or a c with the a -> Either b c, feeds it to either the original f b or the original f c, and then re-injects the output back into a a with the b -> a or the c -> a.

Since: 0.4.0.0

Minimal complete definition

swerve | swerved

Methods

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

Like <!>, decide, or choose, but requires both an injecting and a choosing function.

It is used to merge f b (producer and consumer of b) and f c (producer and consumer of c) into a f a in an either-or manner. You can think of it as, for the f a, it "chooses" if the a is actually a b or a c with the a -> Either b c, feeds it to either the original f b or the original f c, and then re-injects the output back into a a with the b -> a or the c -> a.

An important property is that it will only ever use exactly one of the options given in order to fulfil its job. If you swerve an f a and an f b into an f c, in order to consume/produdce the c, it will only use either the f a or the f b -- exactly one of them.

Since: 0.4.0.0

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

A simplified version of swerive that splits to and from an Either. You can then use invmap to reshape it into the proper shape.

Since: 0.4.0.0

Instances

Instances details
FreeOf Inalt DecAlt1 Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Associated Types

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

Methods

fromFree :: forall (f :: Type -> Type). DecAlt1 f ~> Final Inalt f Source #

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

Inalt (DecAlt f) Source # 
Instance details

Defined in Data.Functor.Invariant.Internative.Free

Methods

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

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

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

Defined in Data.Functor.Invariant.Internative.Free

Methods

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

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

Invariant (Final Inalt f)

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

invmap :: (a -> b) -> (b -> a) -> Final Inalt f a -> Final Inalt f b

Invariant f => Inalt (Chain1 Night f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Chain

Methods

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

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

Inalt (Final Internative f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

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

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

Inalt (Final Inplus f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

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

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

Inalt (Final Inalt f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

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

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

Inalt (Chain Night Not f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Chain

Methods

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

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

class Inalt f => Inplus f where Source #

The invariant counterpart of Alt and Conclude.

The main important action is described in Inalt, but this adds reject, which is the counterpart to empty and conclude and conquer. It's the identity to swerve; if combine two f as with swerve, and one of them is reject, then that banch will never be taken.

Conceptually, if you think of swerve as "choosing one path and re-injecting back", then reject introduces a branch that is impossible to take.

Methods

reject :: (a -> Void) -> f a Source #

Instances

Instances details
FreeOf Inplus DecAlt Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Associated Types

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

Methods

fromFree :: forall (f :: Type -> Type). DecAlt f ~> Final Inplus f Source #

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

Inplus (DecAlt f) Source # 
Instance details

Defined in Data.Functor.Invariant.Internative.Free

Methods

reject :: (a -> Void) -> DecAlt f a Source #

Invariant (Final Inplus f)

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

invmap :: (a -> b) -> (b -> a) -> Final Inplus f a -> Final Inplus f b

Inplus (Final Internative f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

reject :: (a -> Void) -> Final Internative f a Source #

Inplus (Final Inplus f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

reject :: (a -> Void) -> Final Inplus f a Source #

Inalt (Final Inplus f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

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

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

Inplus (Chain Night Not f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Chain

Methods

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

class (Inplus f, Inplicative f) => Internative f Source #

The invariant counterpart to Alternative and Decidable: represents a combination of both Applicative and Alt, or Divisible and Conclude. There are laws?

Instances

Instances details
Invariant (Final Internative f)

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

invmap :: (a -> b) -> (b -> a) -> Final Internative f a -> Final Internative f b

Inplicative (Final Internative f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

knot :: a -> Final Internative f a Source #

Inply (Final Internative f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

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

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

Inplus (Final Internative f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

reject :: (a -> Void) -> Final Internative f a Source #

Inalt (Final Internative f) Source #

Since: 0.4.0.0

Instance details

Defined in Data.HFunctor.Final

Methods

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

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

Assembling Helpers

concatInplus :: Inplus f => NP f as -> f (NS I as) Source #

Convenient wrapper to build up an Inplus instance on by providing each branch 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 and Inplus instance 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) $
  concatInplus $ 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 directly.
  • If you have 2 components, use swerve directly.
  • If you have 3 or more components, these combinators may be useful; otherwise you'd need to manually peel off eithers one-by-one.

concatInalt :: Inalt f => NP f (a ': as) -> f (NS I (a ': as)) Source #

A version of concatInplus for non-empty NP, but only requiring an Inalt instance.

Since: 0.4.0.0