Copyright | (c) Justin Le 2019 |
---|---|
License | BSD3 |
Maintainer | justin@jle.im |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
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
Knot
directly. - If you have 1 component, use
inject
orinjectChain
directly. - If you have 2 components, use
toListBy
ortoChain
. - 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
.