| Copyright | (c) Justin Le 2019 |
|---|---|
| License | BSD3 |
| Maintainer | justin@jle.im |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.Functor.Invariant.Day
Contents
Description
Provides an Invariant version of the typical Haskell Day convolution
over tuples.
Since: 0.3.0.0
Synopsis
- data Day :: (Type -> Type) -> (Type -> Type) -> Type -> Type where
- day :: f a -> g b -> Day f g (a, b)
- runDayApply :: forall f g h. Apply h => (f ~> h) -> (g ~> h) -> Day f g ~> h
- runDayDivise :: forall f g h. Divise h => (f ~> h) -> (g ~> h) -> Day f g ~> h
- toCoDay :: Day f g ~> Day f g
- toContraDay :: Day f g ~> Day f g
- assoc :: Day f (Day g h) ~> Day (Day f g) h
- unassoc :: Day (Day f g) h ~> Day f (Day g h)
- intro1 :: g ~> Day Identity g
- intro2 :: f ~> Day f Identity
- elim1 :: Invariant g => Day Identity g ~> g
- elim2 :: Invariant f => Day f Identity ~> f
- swapped :: Day f g ~> Day g f
- trans1 :: (f ~> h) -> Day f g ~> Day h g
- trans2 :: (g ~> h) -> Day f g ~> Day f h
- type DayChain = Chain Day Identity
- pattern Gather :: (a -> (b, c)) -> (b -> c -> a) -> f b -> DayChain f c -> DayChain f a
- pattern Knot :: a -> DayChain f a
- runCoDayChain :: forall f g. Applicative g => (f ~> g) -> DayChain f ~> g
- runContraDayChain :: forall f g. Divisible g => (f ~> g) -> DayChain f ~> g
- chainAp :: DayChain f ~> Ap f
- chainDiv :: DayChain f ~> Div f
- assembleDayChain :: NP f as -> DayChain f (NP I as)
- assembleDayChainRec :: Rec f as -> DayChain f (XRec Identity as)
- concatDayChain :: NP (DayChain f) as -> DayChain f (NP I as)
- concatDayChainRec :: Rec (DayChain f) as -> DayChain f (XRec Identity as)
- type DayChain1 = Chain1 Day
- pattern DayChain1 :: Invariant f => (a -> (b, c)) -> (b -> c -> a) -> f b -> DayChain f c -> DayChain1 f a
- runCoDayChain1 :: forall f g. Apply g => (f ~> g) -> DayChain1 f ~> g
- runContraDayChain1 :: forall f g. Divise g => (f ~> g) -> DayChain1 f ~> g
- chainAp1 :: DayChain1 f ~> Ap1 f
- chainDiv1 :: DayChain1 f ~> Div1 f
- assembleDayChain1 :: Invariant f => NP f (a ': as) -> DayChain1 f (NP I (a ': as))
- assembleDayChain1Rec :: Invariant f => Rec f (a ': as) -> DayChain1 f (XRec Identity (a ': as))
- concatDayChain1 :: Invariant f => NP (DayChain1 f) (a ': as) -> DayChain1 f (NP I (a ': as))
- concatDayChain1Rec :: Invariant f => Rec (DayChain1 f) (a ': as) -> DayChain1 f (XRec Identity (a ': as))
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 is a invariant "consumer" and "producer" of Day f g aa, 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 . This is a consumer/producer of day x y ::
Day f g (a, b)(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.
Instances
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.
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.
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.
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
Knotdirectly. - If you have 1 component, use
injectorinjectChaindirectly. - If you have 2 components, use
toListByortoChain. - 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 #
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.