Copyright  (c) Justin Le 2019 

License  BSD3 
Maintainer  justin@jle.im 
Stability  experimental 
Portability  nonportable 
Safe Haskell  None 
Language  Haskell2010 
Functor combinators and tools (typeclasses and utiility functions) to manipulate them. This is the main "entrypoint" of the library.
Classes include:
HFunctor
andHBifunctor
, used to swap out the functors that the combinators modifyInterpret
,Associative
,Monoidal
, used to inject and interpret functor values with respect to their combinators.
We have some helpful utility functions, as well, built on top of these typeclasses.
The second half of this module exports the various useful functor combinators that can modify functors to add extra functionality, or join two functors together and mix them in different ways. Use them to build your final structure by combining simpler ones in composable ways!
See https://blog.jle.im/entry/functorcombinatorpedia.html and the README for a tutorial and a rundown on each different functor combinator.
Synopsis
 type (~>) (f :: k > Type) (g :: k > Type) = forall (x :: k). f x > g x
 type (<~>) f g = forall p a. Profunctor p => p (g a) (g a) > p (f a) (f a)
 class HFunctor t where
 class HFunctor t => Inject t where
 class Inject t => Interpret t where
 forI :: (Interpret t, C t g) => t f a > (f ~> g) > g a
 getI :: (Interpret t, C t (Const b)) => (forall x. f x > b) > t f a > b
 collectI :: (Interpret t, C t (Const [b])) => (forall x. f x > b) > t f a > [b]
 class HBifunctor t where
 class HBifunctor t => Associative t where
 associating :: (Functor f, Functor g, Functor h) => t f (t g h) <~> t (t f g) h
 class (Associative t, Interpret (SF t)) => Semigroupoidal t where
 type CS t = C (SF t)
 biget :: (Semigroupoidal t, CS t (Const b)) => (forall x. f x > b) > (forall x. g x > b) > t f g a > b
 bicollect :: (Semigroupoidal t, CS t (Const [b])) => (forall x. f x > b) > (forall x. g x > b) > t f g a > [b]
 (!*!) :: (Semigroupoidal t, CS t h) => (f ~> h) > (g ~> h) > t f g ~> h
 (!$!) :: (Semigroupoidal t, CS t (Const b)) => (forall x. f x > b) > (forall x. g x > b) > t f g a > b
 class Associative t => Tensor t where
 class (Tensor t, Semigroupoidal t, Interpret (MF t)) => Monoidal t where
 type CM t = C (MF t)
 nilMF :: forall t f. Monoidal t => I t ~> MF t f
 consMF :: Monoidal t => t f (MF t f) ~> MF t f
 inL :: forall t f g. (Monoidal t, CM t g) => f ~> t f g
 inR :: forall t f g. (Monoidal t, CM t f) => g ~> t f g
 outL :: (Tensor t, I t ~ Proxy, Functor f) => t f g ~> f
 outR :: (Tensor t, I t ~ Proxy, Functor g) => t f g ~> g
 data Coyoneda (f :: Type > Type) a where
 newtype ListF f a = ListF {
 runListF :: [f a]
 newtype NonEmptyF f a where
 NonEmptyF {
 runNonEmptyF :: NonEmpty (f a)
 pattern ProdNonEmpty :: (f :*: ListF f) a > NonEmptyF f a
 NonEmptyF {
 newtype MaybeF f a = MaybeF {}
 newtype MapF k f a = MapF {}
 newtype NEMapF k f a = NEMapF {}
 data Ap (f :: Type > Type) a
 data Ap1 :: (Type > Type) > Type > Type where
 data Alt (f :: Type > Type) a
 data Free f a
 data Free1 f a
 data Lift (f :: Type > Type) a
 data Step f a = Step {}
 newtype Steps f a = Steps {}
 data ProxyF f a = ProxyF
 data ConstF e f a = ConstF {
 getConstF :: e
 data EnvT e (w :: Type > Type) a = EnvT e (w a)
 newtype ReaderT r (m :: k > Type) (a :: k) :: forall k. Type > (k > Type) > k > Type = ReaderT {
 runReaderT :: r > m a
 data Flagged f a = Flagged {
 flaggedFlag :: Bool
 flaggedVal :: f a
 newtype IdentityT (f :: k > Type) (a :: k) :: forall k. (k > Type) > k > Type = IdentityT {
 runIdentityT :: f a
 data Void2 a b
 newtype Final c f a = Final {
 runFinal :: forall g. c g => (forall x. f x > g x) > g a
 class Interpret t => FreeOf c t  t > c where
 newtype ComposeT (f :: (Type > Type) > Type > Type) (g :: (Type > Type) > Type > Type) (m :: Type > Type) a = ComposeT {
 getComposeT :: f (g m) a
 data Day (f :: Type > Type) (g :: Type > Type) a where
 data ((f :: k > Type) :*: (g :: k > Type)) (p :: k) :: forall k. (k > Type) > (k > Type) > k > Type = (f p) :*: (g p)
 prodOutL :: (f :*: g) ~> f
 prodOutR :: (f :*: g) ~> g
 data ((f :: k > Type) :+: (g :: k > Type)) (p :: k) :: forall k. (k > Type) > (k > Type) > k > Type
 data V1 (p :: k) :: forall k. k > Type
 data These1 (f :: Type > Type) (g :: Type > Type) a
 data Comp f g a where
 newtype LeftF f g a = LeftF {
 runLeftF :: f a
 newtype RightF f g a = RightF {
 runRightF :: g a
 data HLift t f a
 data HFree t f a
 generalize :: Applicative f => Identity ~> f
 absorb :: f ~> Proxy
Classes
A lot of type signatures are stated in terms of ~>
. ~>
represents a "natural transformation" between two functors: a value of
type f
is a value of type 'f a > g a~>
g that works for any
a@.
type (~>) (f :: k > Type) (g :: k > Type) = forall (x :: k). f x > g x infixr 0 #
A natural transformation from f
to g
.
type (<~>) f g = forall p a. Profunctor p => p (g a) (g a) > p (f a) (f a) infixr 0 Source #
The type of an isomorphism between two functors. f
means that
<~>
gf
and g
are isomorphic to each other.
We can effectively use an f <~> g
with:
viewF
:: (f <~> g) > f a > g areviewF
:: (f <~> g) > g a > a a
Use viewF
to extract the "f
to g
" function, and reviewF
to
extract the "g
to f
" function. Reviewing and viewing the same value
(or vice versa) leaves the value unchanged.
One nice thing is that we can compose isomorphisms using .
from
Prelude:
(.
) :: f <~> g
> g <~> h
> f <~> h
Another nice thing about this representation is that we have the
"identity" isomorphism by using id
from Prelude.
id
:: f<~>
g
As a convention, most isomorphisms have form "Xing", where the forwards function is "ing". For example, we have:
splittingSF
::Monoidal
t =>SF
t a<~>
t f (MF
t f)splitSF
:: Monoidal t => SF t a~>
t f (MF t f)
Single Functors
Classes that deal with singlefunctor combinators, that enhance a single functor.
class HFunctor t where Source #
An HFunctor
can be thought of a unary "functor transformer" 
a basic functor combinator. It takes a functor as input and returns
a functor as output.
It "enhances" a functor with extra structure (sort of like how a monad
transformer enhances a Monad
with extra structure).
As a uniform inteface, we can "swap the underlying functor" (also
sometimes called "hoisting"). This is what hmap
does: it lets us swap
out the f
in a t f
for a t g
.
For example, the free monad Free
takes a Functor
and returns a new
Functor
. In the process, it provides a monadic structure over f
.
hmap
lets us turn a
into a Free
f
: a monad built over
Free
gf
can be turned into a monad built over g
.
For the ability to move in and out of the enhanced functor, see
Inject
and Interpret
.
This class is similar to MFunctor
from
Control.Monad.Morph, but instances must work without a Monad
constraint.
This class is also found in the hschema library with the same name.
hmap :: (f ~> g) > t f ~> t g Source #
If we can turn an f
into a g
, then we can turn a t f
into
a t g
.
It must be the case that
hmap
id
== id
Essentially, t f
adds some "extra structure" to f
. hmap
must swap out the functor, without affecting the added structure.
For example,
is essentially a list of ListF
f af a
s. If we
hmap
to swap out the f a
s for g a
s, then we must ensure that
the "added structure" (here, the number of items in the list, and
the ordering of those items) remains the same. So, hmap
must
preserve the number of items in the list, and must maintain the
ordering.
The law
is a way of formalizing this property.hmap
id
== id
Instances
class HFunctor t => Inject t where Source #
A typeclass for HFunctor
s where you can "inject" an f a
into a t
f a
:
inject
:: f a > t f a
If you think of t f a
as an "enhanced f
", then inject
allows you
to use an f
as its enhanced form.
With the exception of directly pattern matching on the result, inject
itself is not too useful in the general case without
Interpret
to allow us to interpret or retrieve
back the f
.
Lift from f
into the enhanced t f
structure. Analogous to
lift
from MonadTrans
.
Note that this lets us "lift" a f a
; if you want to lift an a
with a > t f a
, check if t f
is an instance of Applicative
or
Pointed
.
Instances
class Inject t => Interpret t where Source #
An Interpret
lets us move in and out of the "enhanced" Functor
.
For example,
is Free
ff
enhanced with monadic structure. We get:
inject
:: f a >Free
f ainterpret
::Monad
m => (forall x. f x > m x) >Free
f a > m a
inject
will let us use our f
inside the enhanced
.
Free
finterpret
will let us "extract" the f
from a
if
we can give an interpreting function that interprets Free
ff
into some
target Monad
.
The type family C
tells us the typeclass constraint of the "target"
functor. For Free
, it is Monad
, but for other Interpret
instances, we might have other constraints.
We enforce that:
interpret
id .inject
== id  orretract
.inject
== id
That is, if we lift a value into our structure, then immediately interpret it out as itself, it should lave the value unchanged.
retract :: C t f => t f ~> f Source #
Remove the f
out of the enhanced t f
structure, provided that
f
satisfies the necessary constraints. If it doesn't, it needs to
be properly interpret
ed out.
interpret :: C t g => (f ~> g) > t f ~> g Source #
Given an "interpeting function" from f
to g
, interpret the f
out of the t f
into a final context g
.
Instances
Interpret Ap Source #  A free 
Interpret Ap Source #  A free 
Interpret Ap Source #  A free 
Interpret Alt Source #  A free 
Interpret Coyoneda Source #  A free 
Interpret WrappedApplicative Source #  
Defined in Data.HFunctor.Interpret type C WrappedApplicative :: (Type > Type) > Constraint Source # retract :: C WrappedApplicative f => WrappedApplicative f ~> f Source # interpret :: C WrappedApplicative g => (f ~> g) > WrappedApplicative f ~> g Source #  
Interpret MaybeApply Source #  A free 
Defined in Data.HFunctor.Interpret type C MaybeApply :: (Type > Type) > Constraint Source # retract :: C MaybeApply f => MaybeApply f ~> f Source # interpret :: C MaybeApply g => (f ~> g) > MaybeApply f ~> g Source #  
Interpret Lift Source #  A free 
Interpret ListF Source #  A free 
Interpret NonEmptyF Source #  A free 
Interpret MaybeF Source #  Technically, 
Interpret Free1 Source #  A free 
Interpret Free Source #  A free 
Interpret Ap1 Source #  
Monoid e => Interpret (EnvT e) Source #  
Interpret (IdentityT :: (Type > Type) > Type > Type) Source #  A free 
Interpret (These1 f) Source #  Technically, 
Interpret (Reverse :: (Type > Type) > Type > Type) Source #  
Interpret (Backwards :: (Type > Type) > Type > Type) Source #  
Monoid k => Interpret (MapF k) Source #  
Monoid k => Interpret (NEMapF k) Source #  
Interpret (Step :: (Type > Type) > Type > Type) Source #  
Interpret (Steps :: (Type > Type) > Type > Type) Source #  
Interpret (Flagged :: (Type > Type) > Type > Type) Source #  
Interpret (Final c) Source #  
Interpret ((:+:) f) Source #  Technically, 
Plus f => Interpret ((:*:) f) Source #  
Plus f => Interpret (Product f) Source #  
Interpret (Sum f) Source #  Technically, 
(Interpret s, Interpret t) => Interpret (ComposeT s t) Source #  
Interpret (ReaderT r :: (Type > Type) > Type > Type) Source #  A free 
Interpret (ProxyF :: (Type > Type) > Type > Type) Source #  The only way for this to obey 
Interpret t => Interpret (HFree t) Source #  Never uses 
Interpret t => Interpret (HLift t) Source #  Never uses 
(HBifunctor t, Semigroupoidal t) => Interpret (Chain1 t) Source #  
Interpret (M1 i c :: (Type > Type) > Type > Type) Source #  
Monoid e => Interpret (ConstF e :: (Type > Type) > Type > Type) Source #  The only way for this to obey 
Interpret (RightF f :: (Type > Type) > Type > Type) Source #  
(Monoidal t, i ~ I t) => Interpret (Chain t i) Source #  We can collapse and interpret an 
forI :: (Interpret t, C t g) => t f a > (f ~> g) > g a Source #
A convenient flipped version of interpret
.
getI :: (Interpret t, C t (Const b)) => (forall x. f x > b) > t f a > b Source #
Useful wrapper over interpret
to allow you to directly extract
a value b
out of the t f a
, if you can convert f x
into b
.
Note that depending on the constraints on the interpretation of t
, you
may have extra constraints on b
.
 If
isC
tUnconstrained
, there are no constraints onb
 If
isC
tApply
,b
needs to be an instance ofSemigroup
 If
isC
tApplicative
,b
needs to be an instance ofMonoid
For some constraints (like Monad
), this will not be usable.
 get the length of theMap String
in theStep
.collectI
length :: Step (Map String) Bool > Int
collectI :: (Interpret t, C t (Const [b])) => (forall x. f x > b) > t f a > [b] Source #
Useful wrapper over getI
to allow you to collect a b
from all
instances of f
inside a t f a
.
This will work if
is C
tUnconstrained
, Apply
, or Applicative
.
 get the lengths of allMap String
s in theAp
.collectI
length :: Ap (Map String) Bool > [Int]
MultiFunctors
Classes that deal with twofunctor combinators, that "mix" two functors together in some way.
class HBifunctor t where Source #
A HBifunctor
is like an HFunctor
, but it enhances two different
functors instead of just one.
Usually, it enhaces them "together" in some sort of combining way.
This typeclass provides a uniform instance for "swapping out" or
"hoisting" the enhanced functors. We can hoist the first one with
hleft
, the second one with hright
, or both at the same time with
hbimap
.
For example, the f :*: g
type gives us "both f
and g
":
data (f :*:
g) a = f a :*: g a
It combines both f
and g
into a unified structure  here, it does
it by providing both f
and g
.
The single law is:
hbimap
id
id == id
This ensures that hleft
, hright
, and hbimap
do not affect the
structure that t
adds on top of the underlying functors.
hleft :: (f ~> j) > t f g ~> t j g Source #
Swap out the first transformed functor.
hright :: (g ~> k) > t f g ~> t f k Source #
Swap out the second transformed functor.
hbimap :: (f ~> j) > (g ~> k) > t f g ~> t j k Source #
Swap out both transformed functors at the same time.
Instances
HBifunctor (Sum :: (k > Type) > (k > Type) > k > Type) Source #  
HBifunctor ((:+:) :: (k > Type) > (k > Type) > k > Type) Source #  
HBifunctor (Product :: (k > Type) > (k > Type) > k > Type) Source #  
HBifunctor ((:*:) :: (k > Type) > (k > Type) > k > Type) Source #  
HBifunctor (Joker :: (k2 > Type) > (k1 > Type) > k2 > Type) Source #  
HBifunctor (LeftF :: (k2 > Type) > (k1 > Type) > k2 > Type) Source #  
HBifunctor (RightF :: (k1 > Type) > (k2 > Type) > k2 > Type) Source #  
HBifunctor (Void3 :: (k1 > Type) > (k2 > Type) > k3 > Type) Source #  
HBifunctor Day Source #  
HBifunctor These1 Source #  
HBifunctor Comp Source #  
Associative
class HBifunctor t => Associative t where Source #
An HBifunctor
where it doesn't matter which binds first is
Associative
. Knowing this gives us a lot of power to rearrange the
internals of our HFunctor
at will.
For example, for the functor product:
data (f :*:
g) a = f a :*: g a
We know that f :*: (g :*: h)
is the same as (f :*: g) :*: h
.
Instances
Associative Day Source #  
Associative These1 Source #  
Associative Comp Source #  
Associative ((:+:) :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Associative ((:*:) :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Associative (Product :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Associative (Sum :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Associative (Joker :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Associative (LeftF :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Associative (RightF :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Associative (Void3 :: (Type > Type) > (Type > Type) > Type > Type) Source #  
class (Associative t, Interpret (SF t)) => Semigroupoidal t where Source #
For some t
s, you can represent the act of applying a functor f
to
t
many times, as a single type. That is, there is some type
that is equivalent to one of:SF
t f
f a
 1 timet f f a
 2 timest f (t f f) a
 3 timest f (t f (t f f)) a
 4 timest f (t f (t f (t f f))) a
 5 times .. etc
This typeclass associates each t
with its "induced semigroupoidal
functor combinator"
.SF
t
This is useful because sometimes you might want to describe a type that
can be t f f
, t f (t f f)
, t f (t f (t f f))
, etc.; "f applied to
itself", with at least one f
. This typeclass lets you use a type like
NonEmptyF
in terms of repeated applications of :*:
, or Ap1
in
terms of repeated applications of Day
, or Free1
in terms of repeated
applications of Comp
, etc.
For example, f
can be interpreted as "a free selection of two
:*:
ff
s", allowing you to specify "I have to f
s that I can use". If you
want to specify "I want 1, 2, or many different f
s that I can use",
you can use
.NonEmptyF
f
At the high level, the main way to use a Semigroupoidal
is with
biretract
and binterpret
:
biretract
:: t f f~>
fbinterpret
:: (f ~> h) > (g ~> h) > t f g ~> h
which are like the HBifunctor
versions of retract
and interpret
:
they fully "mix" together the two inputs of t
.
Also useful is:
toSF
:: t f f a > SF t f a
Which converts a t
into its aggregate type SF
.
In reality, most Semigroupoidal
instances are also
Monoidal
instances, so you can think of the
separation as mostly to help organize functionality. However, there are
two nonmonoidal semigroupoidal instances of note: LeftF
and RightF
,
which are higher order analogues of the First
and
Last
semigroups, roughly.
type SF t :: (Type > Type) > Type > Type Source #
The "semigroup functor combinator" generated by t
.
A value of type SF t f a
is equivalent to one of:
f a
t f f a
t f (t f f) a
t f (t f (t f f)) a
t f (t f (t f (t f f))) a
 .. etc
For example, for :*:
, we have NonEmptyF
. This is because:
x ~NonEmptyF
(x:
[]) ~inject
x x:*:
y ~ NonEmptyF (x : [y]) ~toSF
(x :*: y) x :*: y :*: z ~ NonEmptyF (x : [y,z])  etc.
You can create an "singleton" one with inject
, or else one from
a single t f f
with toSF
.
appendSF :: t (SF t f) (SF t f) ~> SF t f Source #
If a
represents multiple applications of SF
t ft f
to
itself, then we can also "append" two
s applied to
themselves into one giant SF
t f
containing all of the SF
t ft f
s.
consSF :: t f (SF t f) ~> SF t f Source #
Prepend an application of t f
to the front of a
.SF
t f
toSF :: t f f ~> SF t f Source #
Embed a direct application of f
to itself into a
.SF
t f
biretract :: CS t f => t f f ~> f Source #
The HBifunctor
analogy of retract
. It retracts both f
s
into a single f
, effectively fully mixing them together.
binterpret :: CS t h => (f ~> h) > (g ~> h) > t f g ~> h Source #
The HBifunctor
analogy of interpret
. It takes two
interpreting functions, and mixes them together into a target
functor h
.
Instances
Convenient alias for the constraint required for biretract
,
binterpret
, etc.
It's usually a constraint on the target/result context of interpretation
that allows you to "exit" or "run" a
.Semigroupoidal
t
biget :: (Semigroupoidal t, CS t (Const b)) => (forall x. f x > b) > (forall x. g x > b) > t f g a > b Source #
Useful wrapper over binterpret
to allow you to directly extract
a value b
out of the t f a
, if you can convert f x
into b
.
Note that depending on the constraints on the interpretation of t
, you
may have extra constraints on b
.
 If
isC
(SF
t)Unconstrained
, there are no constraints onb
 If
isC
(SF
t)Apply
,b
needs to be an instance ofSemigroup
 If
isC
(SF
t)Applicative
,b
needs to be an instance ofMonoid
For some constraints (like Monad
), this will not be usable.
 Return the length of either the list, or the Map, depending on which  one s in the+
biget
length
length :: ([] :+:Map
Int
)Char
> Int  Return the length of both the list and the map, added togetherbiget
(Sum
. length) (Sum . length) ::Day
[] (Map Int) Char > Sum Int
bicollect :: (Semigroupoidal t, CS t (Const [b])) => (forall x. f x > b) > (forall x. g x > b) > t f g a > [b] Source #
Useful wrapper over biget
to allow you to collect a b
from all
instances of f
and g
inside a t f g a
.
This will work if
is C
tUnconstrained
,
Apply
, or Applicative
.
(!*!) :: (Semigroupoidal t, CS t h) => (f ~> h) > (g ~> h) > t f g ~> h infixr 5 Source #
Infix alias for binterpret
(!$!) :: (Semigroupoidal t, CS t (Const b)) => (forall x. f x > b) > (forall x. g x > b) > t f g a > b infixr 5 Source #
Tensor
class Associative t => Tensor t where Source #
An Associative
HBifunctor
can be a Tensor
if there is some
identity i
where t i f
is equivalent to just f
.
That is, "enhancing" f
with t i
does nothing.
The methods in this class provide us useful ways of navigating
a
with respect to this property.Tensor
t
The Tensor
is essentially the HBifunctor
equivalent of Inject
,
with intro1
and intro2
taking the place of inject
.
type I t :: Type > Type Source #
The identity of
. If you "combine" Tensor
tf
with the
identity, it leaves f
unchanged.
For example, the identity of :*:
is Proxy
. This is because
(Proxy
:*: f) a
is equivalent to just
f a
:*:
ing f
with Proxy
gives you no additional structure.
Another example:
(V1
:+:
f) a
is equivalent to just
f a
because the L1
case is unconstructable.
intro1 :: f ~> t f (I t) Source #
Because t f (I t)
is equivalent to f
, we can always "insert"
f
into t f (I t)
.
This is analogous to inject
from Inject
, but for HBifunctor
s.
intro2 :: g ~> t (I t) g Source #
Because t (I t) g
is equivalent to f
, we can always "insert"
g
into t (I t) g
.
This is analogous to inject
from Inject
, but for HBifunctor
s.
Instances
Tensor Day Source #  
Tensor These1 Source #  
Tensor Comp Source #  
Tensor ((:+:) :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Tensor ((:*:) :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Tensor (Product :: (Type > Type) > (Type > Type) > Type > Type) Source #  
Tensor (Sum :: (Type > Type) > (Type > Type) > Type > Type) Source #  
class (Tensor t, Semigroupoidal t, Interpret (MF t)) => Monoidal t where Source #
A
is a Monoidal
tSemigroupoidal
, in that it provides some type
that is equivalent to one of:MF
t f
I a
 0 timesf a
 1 timet f f a
 2 timest f (t f f) a
 3 timest f (t f (t f f)) a
 4 timest f (t f (t f (t f f))) a
 5 times .. etc
The difference is that unlike
, SF
t
has the "zero times"
value.MF
t
This typeclass lets you use a type like ListF
in terms of repeated
applications of :*:
, or Ap
in terms of repeated applications of
Day
, or Free
in terms of repeated applications of Comp
, etc.
For example, f
can be interpreted as "a free selection of two
:*:
ff
s", allowing you to specify "I have to f
s that I can use". If you
want to specify "I want 0, 1, or many different f
s that I can use",
you can use
.ListF
f
At the high level, the thing that Monoidal
adds to Semigroupoidal
is inL
, inR
, and nilMF
:
inL
:: f a > t f g ainR
:: g a > t f g anilMF
:: I a > MF t f a
which are like the HBifunctor
versions of inject
: it lets you inject
an f
into t f g
, so you can start doing useful mixing operations
with it. nilMF
lets you construct an "empty"
.MF
t
Also useful is:
toMF
:: t f f a > MF t f a
Which converts a t
into its aggregate type MF
type MF t :: (Type > Type) > Type > Type Source #
The "monoidal functor combinator" induced by t
.
A value of type MF t f a
is equivalent to one of:
I a
 zero fsf a
 one ft f f a
 two fst f (t f f) a
 three fst f (t f (t f f)) a
t f (t f (t f (t f f))) a
 .. etc
For example, for :*:
, we have ListF
. This is because:
Proxy
~ListF
[] ~nilMF
@(:*:
) x ~ ListF [x] ~inject
x x :*: y ~ ListF [x,y] ~toMF
(x :*: y) x :*: y :*: z ~ ListF [x,y,z]  etc.
You can create an "empty" one with nilMF
, a "singleton" one with
inject
, or else one from a single t f f
with toMF
.
appendMF :: t (MF t f) (MF t f) ~> MF t f Source #
If a
represents multiple applications of MF
t ft f
to
itself, then we can also "append" two
s applied to
themselves into one giant MF
t f
containing all of the MF
t ft f
s.
splitSF :: SF t f ~> t f (MF t f) Source #
Lets you convert an
into a single application of SF
t ff
to
.MF
t f
Analogous to a function NonEmpty
a > (a,
[a])
Note that this is not reversible in general unless we have
.Matchable
t
toMF :: t f f ~> MF t f Source #
Embed a direct application of f
to itself into a
.MF
t f
fromSF :: SF t f ~> MF t f Source #
is "one or more SF
t ff
s", and 'MF t f
is "zero or more
f
s". This function lets us convert from one to the other.
This is analogous to a function
.NonEmpty
a >
[a]
Note that because t
is not inferrable from the input or output
type, you should call this using XTypeApplications:
fromSF
@(:*:
) ::NonEmptyF
f a >ListF
f a fromSF @Comp
::Free1
f a >Free
f a
pureT :: CM t f => I t ~> f Source #
If we have an
, we can generate an I
tf
based on how it
interacts with t
.
Specialized (and simplified), this type is:
pureT
@Day
::Applicative
f =>Identity
a > f a pure
pureT @Comp
::Monad
f => Identity a > f a return
pureT @(:*:
) ::Plus
f =>Proxy
a > f a zero
Note that because t
appears nowhere in the input or output types,
you must always use this with explicit type application syntax (like
pureT @Day
)
upgradeC :: CM t f => proxy f > (CS t f => r) > r Source #
If we have a constraint on the Monoidal
satisfied, it should
also imply the constraint on the Semigroupoidal
.
This is basically saying that
should be a superclass
of C
(SF
t)
.C
(MF
t)
For example, for :*:
, this type signature says that Alt
is
a superclass of Plus
, so whenever you have Plus
, you should
always also have Alt
.
For Day
, this type signature says that Apply
is a superclass of
Applicative
, so whenever you have Applicative
, you should always
also have Apply
.
This is necessary because in the current class hierarchy, Apply
isn't a true superclass of Applicative
. upgradeC
basically
"imbues" f
with an Apply
instance based on its Applicative
instance, so things can be easier to use.
For example, let's say I have a type Parser
that is an
Applicative
instance, but the source library does not define an
Apply
instance. I cannot use biretract
or binterpret
with it,
even though I should be able to, because they require Apply
.
That is:
biretract
::Day
Parser Parser a > Parser a
is a type error, because it requires
.Apply
Parser
But, if we know that Parser
has an Applicative
instance, we can
use:
upgradeC
@Day
(Proxy
@Parser)biretract
:: Day Parser Parser a > a
and this will now typecheck properly.
Ideally, Parser
would also have an Apply
instance. But we
cannot control this if an external library defines Parser
.
(Alternatively you can just use biretractT
.)
Note that you should only use this if f
doesn't already have the
SF
constraint. If it does, this could lead to conflicting
instances. Only use this with specific, concrete f
s. Otherwise
this is unsafe and can possibly break coherence guarantees.
The proxy
argument can be provided using something like
, to specify which Proxy
@ff
you want to upgrade.
Instances
nilMF :: forall t f. Monoidal t => I t ~> MF t f Source #
Create the "empty MF
@.
If
represents multiple applications of MF
t ft f
with
itself, then nilMF
gives us "zero applications of f
".
Note that t
cannot be inferred from the input or output type of
nilMF
, so this function must always be called with XTypeApplications:
nilMF
@Day
::Identity
~>
Ap
f nilMF @Comp
:: Identity ~>Free
f nilMF @(:*:
) ::Proxy
~>ListF
f
consMF :: Monoidal t => t f (MF t f) ~> MF t f Source #
Lets us "cons" an application of f
to the front of an
.MF
t f
inL :: forall t f g. (Monoidal t, CM t g) => f ~> t f g Source #
Convenient wrapper over intro1
that lets us introduce an arbitrary
functor g
to the right of an f
.
You can think of this as an HBifunctor
analogue of inject
.
inR :: forall t f g. (Monoidal t, CM t f) => g ~> t f g Source #
Convenient wrapper over intro2
that lets us introduce an arbitrary
functor f
to the right of a g
.
You can think of this as an HBifunctor
analogue of inject
.
Combinators
Functor combinators ** Single
data Coyoneda (f :: Type > Type) a where #
A covariant Functor
suitable for Yoneda reduction
Instances
A list of f a
s. Can be used to describe a product of many different
values of type f a
.
This is the Free Plus
.
Instances
Interpret ListF Source #  A free 
FreeOf Plus ListF Source #  
Functor f => Functor (ListF f) Source #  
Applicative f => Applicative (ListF f) Source #  
Foldable f => Foldable (ListF f) Source #  
Defined in Control.Applicative.ListF fold :: Monoid m => ListF f m > m # foldMap :: Monoid m => (a > m) > ListF f a > m # foldr :: (a > b > b) > b > ListF f a > b # foldr' :: (a > b > b) > b > ListF f a > b # foldl :: (b > a > b) > b > ListF f a > b # foldl' :: (b > a > b) > b > ListF f a > b # foldr1 :: (a > a > a) > ListF f a > a # foldl1 :: (a > a > a) > ListF f a > a # elem :: Eq a => a > ListF f a > Bool # maximum :: Ord a => ListF f a > a # minimum :: Ord a => ListF f a > a #  
Traversable f => Traversable (ListF f) Source #  
Applicative f => Alternative (ListF f) Source #  
Eq1 f => Eq1 (ListF f) Source #  
Ord1 f => Ord1 (ListF f) Source #  
Defined in Control.Applicative.ListF  
Read1 f => Read1 (ListF f) Source #  
Defined in Control.Applicative.ListF  
Show1 f => Show1 (ListF f) Source #  
Apply f => Apply (ListF f) Source #  
Pointed f => Pointed (ListF f) Source #  
Defined in Control.Applicative.ListF  
Functor f => Plus (ListF f) Source #  
Defined in Control.Applicative.ListF  
Functor f => Alt (ListF f) Source #  
HBind ListF Source #  
Inject ListF Source #  
HFunctor ListF Source #  
Eq (f a) => Eq (ListF f a) Source #  
(Typeable f, Typeable a, Data (f a)) => Data (ListF f a) Source #  
Defined in Control.Applicative.ListF gfoldl :: (forall d b. Data d => c (d > b) > d > c b) > (forall g. g > c g) > ListF f a > c (ListF f a) # gunfold :: (forall b r. Data b => c (b > r) > c r) > (forall r. r > c r) > Constr > c (ListF f a) # toConstr :: ListF f a > Constr # dataTypeOf :: ListF f a > DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) > Maybe (c (ListF f a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) > Maybe (c (ListF f a)) # gmapT :: (forall b. Data b => b > b) > ListF f a > ListF f a # gmapQl :: (r > r' > r) > r > (forall d. Data d => d > r') > ListF f a > r # gmapQr :: (r' > r > r) > r > (forall d. Data d => d > r') > ListF f a > r # gmapQ :: (forall d. Data d => d > u) > ListF f a > [u] # gmapQi :: Int > (forall d. Data d => d > u) > ListF f a > u # gmapM :: Monad m => (forall d. Data d => d > m d) > ListF f a > m (ListF f a) # gmapMp :: MonadPlus m => (forall d. Data d => d > m d) > ListF f a > m (ListF f a) # gmapMo :: MonadPlus m => (forall d. Data d => d > m d) > ListF f a > m (ListF f a) #  
Ord (f a) => Ord (ListF f a) Source #  
Defined in Control.Applicative.ListF  
Read (f a) => Read (ListF f a) Source #  
Show (f a) => Show (ListF f a) Source #  
Generic (ListF f a) Source #  
Semigroup (ListF f a) Source #  
Monoid (ListF f a) Source #  
type C ListF Source #  
Defined in Data.HFunctor.Interpret  
type Rep (ListF f a) Source #  
Defined in Control.Applicative.ListF 
newtype NonEmptyF f a Source #
A nonempty list of f a
s. Can be used to describe a product between
many different possible values of type f a
.
Essentially:
NonEmptyF
f ~ f  one f:+:
(f:*:
f)  two f's :+: (f :*: f :*: f)  three f's :+: (f :*: f :*: f :*: f)  four f's :+: ...  etc.
This is the Free Plus
.
NonEmptyF  

pattern ProdNonEmpty :: (f :*: ListF f) a > NonEmptyF f a  Treat a

Instances
A maybe f a
.
Can be useful for describing a "an f a
that may or may not be there".
This is the free structure for a "fail"like typeclass that would only
have zero :: f a
.
Instances
Interpret MaybeF Source #  Technically, 
Functor f => Functor (MaybeF f) Source #  
Applicative f => Applicative (MaybeF f) Source #  
Foldable f => Foldable (MaybeF f) Source #  
Defined in Control.Applicative.ListF fold :: Monoid m => MaybeF f m > m # foldMap :: Monoid m => (a > m) > MaybeF f a > m # foldr :: (a > b > b) > b > MaybeF f a > b # foldr' :: (a > b > b) > b > MaybeF f a > b # foldl :: (b > a > b) > b > MaybeF f a > b # foldl' :: (b > a > b) > b > MaybeF f a > b # foldr1 :: (a > a > a) > MaybeF f a > a # foldl1 :: (a > a > a) > MaybeF f a > a # elem :: Eq a => a > MaybeF f a > Bool # maximum :: Ord a => MaybeF f a > a # minimum :: Ord a => MaybeF f a > a #  
Traversable f => Traversable (MaybeF f) Source #  
Defined in Control.Applicative.ListF  
Applicative f => Alternative (MaybeF f) Source #  
Eq1 f => Eq1 (MaybeF f) Source #  
Ord1 f => Ord1 (MaybeF f) Source #  
Defined in Control.Applicative.ListF  
Read1 f => Read1 (MaybeF f) Source #  
Defined in Control.Applicative.ListF  
Show1 f => Show1 (MaybeF f) Source #  
Pointed f => Pointed (MaybeF f) Source #  
Defined in Control.Applicative.ListF  
Functor f => Plus (MaybeF f) Source #  
Defined in Control.Applicative.ListF  
Functor f => Alt (MaybeF f) Source #  
HBind MaybeF Source #  
Inject MaybeF Source #  
HFunctor MaybeF Source #  
Eq (f a) => Eq (MaybeF f a) Source #  
(Typeable f, Typeable a, Data (f a)) => Data (MaybeF f a) Source #  
Defined in Control.Applicative.ListF gfoldl :: (forall d b. Data d => c (d > b) > d > c b) > (forall g. g > c g) > MaybeF f a > c (MaybeF f a) # gunfold :: (forall b r. Data b => c (b > r) > c r) > (forall r. r > c r) > Constr > c (MaybeF f a) # toConstr :: MaybeF f a > Constr # dataTypeOf :: MaybeF f a > DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) > Maybe (c (MaybeF f a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) > Maybe (c (MaybeF f a)) # gmapT :: (forall b. Data b => b > b) > MaybeF f a > MaybeF f a # gmapQl :: (r > r' > r) > r > (forall d. Data d => d > r') > MaybeF f a > r # gmapQr :: (r' > r > r) > r > (forall d. Data d => d > r') > MaybeF f a > r # gmapQ :: (forall d. Data d => d > u) > MaybeF f a > [u] # gmapQi :: Int > (forall d. Data d => d > u) > MaybeF f a > u # gmapM :: Monad m => (forall d. Data d => d > m d) > MaybeF f a > m (MaybeF f a) # gmapMp :: MonadPlus m => (forall d. Data d => d > m d) > MaybeF f a > m (MaybeF f a) # gmapMo :: MonadPlus m => (forall d. Data d => d > m d) > MaybeF f a > m (MaybeF f a) #  
Ord (f a) => Ord (MaybeF f a) Source #  
Read (f a) => Read (MaybeF f a) Source #  
Show (f a) => Show (MaybeF f a) Source #  
Generic (MaybeF f a) Source #  
Semigroup (MaybeF f a) Source #  Picks the first 
Monoid (MaybeF f a) Source #  
type C MaybeF Source #  
Defined in Data.HFunctor.Interpret  
type Rep (MaybeF f a) Source #  
Defined in Control.Applicative.ListF 
A map of f a
s, indexed by keys of type k
. It can be useful for
represeting a product of many different values of type f a
, each "at"
a different k
location.
Can be considered a combination of EnvT
and
ListF
, in a way  a
is like a MapF
k f a
with unique (and ordered)
keys.ListF
(EnvT
k f) a
One use case might be to extend a schema with many "options", indexed by some string.
For example, if you had a command line argument parser for a single command
data Command a
Then you can represent a command line argument parser for multiple named commands with
type Commands =MapF
String
Command
See NEMapF
for a nonempty variant, if you want to enforce that your
bag has at least one f a
.
Instances
Monoid k => Interpret (MapF k) Source #  
Monoid k => Inject (MapF k :: (Type > Type) > Type > Type) Source #  Injects into a singleton map at 
HFunctor (MapF k :: (Type > Type) > Type > Type) Source #  
Functor f => Functor (MapF k f) Source #  
Foldable f => Foldable (MapF k f) Source #  
Defined in Control.Applicative.ListF fold :: Monoid m => MapF k f m > m # foldMap :: Monoid m => (a > m) > MapF k f a > m # foldr :: (a > b > b) > b > MapF k f a > b # foldr' :: (a > b > b) > b > MapF k f a > b # foldl :: (b > a > b) > b > MapF k f a > b # foldl' :: (b > a > b) > b > MapF k f a > b # foldr1 :: (a > a > a) > MapF k f a > a # foldl1 :: (a > a > a) > MapF k f a > a # elem :: Eq a => a > MapF k f a > Bool # maximum :: Ord a => MapF k f a > a # minimum :: Ord a => MapF k f a > a #  
Traversable f => Traversable (MapF k f) Source #  
Defined in Control.Applicative.ListF  
(Eq k, Eq1 f) => Eq1 (MapF k f) Source #  
(Ord k, Ord1 f) => Ord1 (MapF k f) Source #  
Defined in Control.Applicative.ListF  
(Ord k, Read k, Read1 f) => Read1 (MapF k f) Source #  
Defined in Control.Applicative.ListF  
(Show k, Show1 f) => Show1 (MapF k f) Source #  
(Monoid k, Pointed f) => Pointed (MapF k f) Source #  
Defined in Control.Applicative.ListF  
(Functor f, Ord k) => Plus (MapF k f) Source #  
Defined in Control.Applicative.ListF  
(Functor f, Ord k) => Alt (MapF k f) Source #  Leftbiased union 
(Eq k, Eq (f a)) => Eq (MapF k f a) Source #  
(Typeable f, Typeable a, Data k, Data (f a), Ord k) => Data (MapF k f a) Source #  
Defined in Control.Applicative.ListF gfoldl :: (forall d b. Data d => c (d > b) > d > c b) > (forall g. g > c g) > MapF k f a > c (MapF k f a) # gunfold :: (forall b r. Data b => c (b > r) > c r) > (forall r. r > c r) > Constr > c (MapF k f a) # toConstr :: MapF k f a > Constr # dataTypeOf :: MapF k f a > DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) > Maybe (c (MapF k f a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) > Maybe (c (MapF k f a)) # gmapT :: (forall b. Data b => b > b) > MapF k f a > MapF k f a # gmapQl :: (r > r' > r) > r > (forall d. Data d => d > r') > MapF k f a > r # gmapQr :: (r' > r > r) > r > (forall d. Data d => d > r') > MapF k f a > r # gmapQ :: (forall d. Data d => d > u) > MapF k f a > [u] # gmapQi :: Int > (forall d. Data d => d > u) > MapF k f a > u # gmapM :: Monad m => (forall d. Data d => d > m d) > MapF k f a > m (MapF k f a) # gmapMp :: MonadPlus m => (forall d. Data d => d > m d) > MapF k f a > m (MapF k f a) # gmapMo :: MonadPlus m => (forall d. Data d => d > m d) > MapF k f a > m (MapF k f a) #  
(Ord k, Ord (f a)) => Ord (MapF k f a) Source #  
(Ord k, Read k, Read (f a)) => Read (MapF k f a) Source #  
(Show k, Show (f a)) => Show (MapF k f a) Source #  
Generic (MapF k f a) Source #  
(Ord k, Alt f) => Semigroup (MapF k f a) Source #  A union, combining matching keys with 
(Ord k, Alt f) => Monoid (MapF k f a) Source #  
type C (MapF k) Source #  
Defined in Data.HFunctor.Interpret  
type Rep (MapF k f a) Source #  
Defined in Control.Applicative.ListF 
A nonempty map of f a
s, indexed by keys of type k
. It can be
useful for represeting a product of many different values of type f a
,
each "at" a different k
location, where you need to have at least one
f a
at all times.
Can be considered a combination of EnvT
and
NonEmptyF
, in a way  an
is like a NEMapF
k f a
with unique (and ordered)
keys.NonEmptyF
(EnvT
k f) a
See MapF
for some use cases.
Instances
Monoid k => Interpret (NEMapF k) Source #  
Monoid k => Inject (NEMapF k :: (Type > Type) > Type > Type) Source #  Injects into a singleton map at 
HFunctor (NEMapF k :: (Type > Type) > Type > Type) Source #  
Functor f => Functor (NEMapF k f) Source #  
Foldable f => Foldable (NEMapF k f) Source #  
Defined in Control.Applicative.ListF fold :: Monoid m => NEMapF k f m > m # foldMap :: Monoid m => (a > m) > NEMapF k f a > m # foldr :: (a > b > b) > b > NEMapF k f a > b # foldr' :: (a > b > b) > b > NEMapF k f a > b # foldl :: (b > a > b) > b > NEMapF k f a > b # foldl' :: (b > a > b) > b > NEMapF k f a > b # foldr1 :: (a > a > a) > NEMapF k f a > a # foldl1 :: (a > a > a) > NEMapF k f a > a # toList :: NEMapF k f a > [a] # null :: NEMapF k f a > Bool # length :: NEMapF k f a > Int # elem :: Eq a => a > NEMapF k f a > Bool # maximum :: Ord a => NEMapF k f a > a # minimum :: Ord a => NEMapF k f a > a #  
Traversable f => Traversable (NEMapF k f) Source #  
Defined in Control.Applicative.ListF  
(Eq k, Eq1 f) => Eq1 (NEMapF k f) Source #  
(Ord k, Ord1 f) => Ord1 (NEMapF k f) Source #  
Defined in Control.Applicative.ListF  
(Ord k, Read k, Read1 f) => Read1 (NEMapF k f) Source #  
Defined in Control.Applicative.ListF  
(Show k, Show1 f) => Show1 (NEMapF k f) Source #  
Foldable1 f => Foldable1 (NEMapF k f) Source #  
(Monoid k, Pointed f) => Pointed (NEMapF k f) Source #  
Defined in Control.Applicative.ListF  
Traversable1 f => Traversable1 (NEMapF k f) Source #  
(Functor f, Ord k) => Alt (NEMapF k f) Source #  Leftbiased union 
(Eq k, Eq (f a)) => Eq (NEMapF k f a) Source #  
(Typeable f, Typeable a, Data k, Data (f a), Ord k) => Data (NEMapF k f a) Source #  
Defined in Control.Applicative.ListF gfoldl :: (forall d b. Data d => c (d > b) > d > c b) > (forall g. g > c g) > NEMapF k f a > c (NEMapF k f a) # gunfold :: (forall b r. Data b => c (b > r) > c r) > (forall r. r > c r) > Constr > c (NEMapF k f a) # toConstr :: NEMapF k f a > Constr # dataTypeOf :: NEMapF k f a > DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) > Maybe (c (NEMapF k f a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) > Maybe (c (NEMapF k f a)) # gmapT :: (forall b. Data b => b > b) > NEMapF k f a > NEMapF k f a # gmapQl :: (r > r' > r) > r > (forall d. Data d => d > r') > NEMapF k f a > r # gmapQr :: (r' > r > r) > r > (forall d. Data d => d > r') > NEMapF k f a > r # gmapQ :: (forall d. Data d => d > u) > NEMapF k f a > [u] # gmapQi :: Int > (forall d. Data d => d > u) > NEMapF k f a > u # gmapM :: Monad m => (forall d. Data d => d > m d) > NEMapF k f a > m (NEMapF k f a) # gmapMp :: MonadPlus m => (forall d. Data d => d > m d) > NEMapF k f a > m (NEMapF k f a) # gmapMo :: MonadPlus m => (forall d. Data d => d > m d) > NEMapF k f a > m (NEMapF k f a) #  
(Ord k, Ord (f a)) => Ord (NEMapF k f a) Source #  
Defined in Control.Applicative.ListF  
(Ord k, Read k, Read (f a)) => Read (NEMapF k f a) Source #  
(Show k, Show (f a)) => Show (NEMapF k f a) Source #  
Generic (NEMapF k f a) Source #  
(Ord k, Alt f) => Semigroup (NEMapF k f a) Source #  A union, combining matching keys with 
type C (NEMapF k) Source #  
Defined in Data.HFunctor.Interpret  
type Rep (NEMapF k f a) Source #  
Defined in Control.Applicative.ListF 
data Ap (f :: Type > Type) a #
The free Applicative
for a Functor
f
.
data Ap1 :: (Type > Type) > Type > Type where Source #
One or more f
s convolved with itself.
Essentially:
Ap1
f ~ f  one f:+:
(f `Day'
f)  two f's :+: (f `Day` f `Day` f)  three f's :+: (f `Day` f `Day` f `Day` f)  four f's :+: ...  etc.
Useful if you want to promote an f
to a situation with "at least one
f
sequenced with itself".
Mostly useful for its HFunctor
and Interpret
instance, along with
its relationship with Ap
and Day
.
This is the free Apply
 Basically a "nonempty" Ap
.
The construction here is based on Ap
, similar to now
NonEmpty
is built on list.
pattern DayAp1 :: Day f (Ap f) a > Ap1 f a  An 
data Alt (f :: Type > Type) a #
Instances
Interpret Alt Source #  A free 
FreeOf Alternative Alt Source #  
Functor (Alt f)  
Applicative (Alt f)  
Alternative (Alt f)  
Apply (Alt f)  
Alt (Alt f)  
HBind Alt Source #  
Inject Alt Source #  
HFunctor Alt Source #  
Semigroup (Alt f a)  
Monoid (Alt f a)  
type C Alt Source #  
Defined in Data.HFunctor.Interpret 
A
is Free
ff
enhanced with "sequential binding" capabilities.
It allows you to sequence multiple f
s one after the other, and also to
determine "what f
to sequence" based on the result of the computation
so far.
Essentially, you can think of this as "giving f
a Monad
instance",
with all that that entails (return
, >>=
, etc.).
Lift f
into it with
. When you finally want to "use" it, you can interpret it into any
monadic context:inject
:: f a > Free
f a
interpret
::Monad
g => (forall x. f x > g x) >Free
f a > g a
Structurally, this is equivalent to many "nested" f's. A value of type
is either:Free
f a
a
f a
f (f a)
f (f (f a))
 .. etc.
Under the hood, this is the Churchencoded Freer monad. It's
Free
, or F
, but in
a way that is compatible with HFunctor
and
Interpret
.