Copyright | (c) Justin Le 2019 |
---|---|
License | BSD3 |
Maintainer | justin@jle.im |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
This module provides an Interpret
able data type of "linked list of
tensor applications".
The type
, for any Chain
t
, is meant to be the same as
Monoidal
t
(the monoidal functor combinator for MF
tt
), and represents "zero
or more" applications of f
to t
.
The type
, for any Chain1
t
, is meant to be the
same as Semigroupoidal
t
(the semigroupoidal functor combinator for SF
tt
) and
represents "one or more" applications of f
to t
.
The advantage of using Chain
and Chain1
over MF
or SF
is that
they provide a universal interface for pattern matching and constructing
such values, which may simplify working with new such functor
combinators you might encounter.
Synopsis
- data Chain t i f a
- foldChain :: forall t i f g. HBifunctor t => (i ~> g) -> (t f g ~> g) -> Chain t i f ~> g
- unfoldChain :: forall t f (g :: Type -> Type) i. HBifunctor t => (g ~> (i :+: t f g)) -> g ~> Chain t i f
- unrollMF :: Monoidal t => MF t f ~> Chain t (I t) f
- rerollMF :: forall t f. Monoidal t => Chain t (I t) f ~> MF t f
- unrollingMF :: Monoidal t => MF t f <~> Chain t (I t) f
- appendChain :: forall t f. Monoidal t => t (Chain t (I t) f) (Chain t (I t) f) ~> Chain t (I t) f
- data Chain1 t f a
- foldChain1 :: forall t f g. HBifunctor t => (f ~> g) -> (t f g ~> g) -> Chain1 t f ~> g
- unfoldChain1 :: forall t f (g :: Type -> Type). HBifunctor t => (g ~> (f :+: t f g)) -> g ~> Chain1 t f
- unrollingSF :: forall t f. (Semigroupoidal t, Functor f) => SF t f <~> Chain1 t f
- unrollSF :: (Semigroupoidal t, Functor f) => SF t f ~> Chain1 t f
- rerollSF :: Semigroupoidal t => Chain1 t f ~> SF t f
- appendChain1 :: forall t f. (Semigroupoidal t, Functor f) => t (Chain1 t f) (Chain1 t f) ~> Chain1 t f
- fromChain1 :: Tensor t => Chain1 t f ~> Chain t (I t) f
- splittingChain1 :: forall t f. (Matchable t, Functor f) => Chain1 t f <~> t f (Chain t (I t) f)
- splitChain1 :: forall t f. Matchable t => Chain1 t f ~> t f (Chain t (I t) f)
- matchingChain :: forall t f. (Matchable t, Functor f) => Chain t (I t) f <~> (I t :+: Chain1 t f)
- unmatchChain :: forall t f. Matchable t => (I t :+: Chain1 t f) ~> Chain t (I t) f
Chain
A useful construction that works like a "linked list" of t f
applied
to itself multiple times. That is, it contains t f f
, t f (t f f)
,
t f (t f (t f f))
, etc, with f
occuring zero or more times. It is
meant to be the same as
.MF
t
If t
is Monoidal
, then it means we can "collapse" this linked list
into some final type
(MF
trerollMF
), and also extract it back
into a linked list (unrollMF
).
So, a value of type
is one of either:Chain
t (I
t) f a
I
t af a
t f f a
t f (t f f) a
t f (t f (t f f)) a
- .. etc.
Note that this is exactly what an
is supposed to be. Using
MF
tChain
allows us to work with all
s in a uniform way, with
normal pattern matching and normal constructors.MF
t
You can fully "collapse" a
into an Chain
t (I t) ff
with
retract
, if t
is Monoidal
; this could be considered a fundamental
property of monoidal-ness.
This construction is inspired by http://oleg.fi/gists/posts/2018-02-21-single-free.html
Instances
HBifunctor t => HFunctor (Chain t i :: (k1 -> Type) -> k2 -> Type) Source # | |
(Tensor t, i ~ I t) => Inject (Chain t i :: (Type -> Type) -> Type -> Type) Source # | |
(Monoidal t, i ~ I t) => Interpret (Chain t i) Source # | We can collapse and interpret an |
(Functor i, Functor (t f (Chain t i f))) => Functor (Chain t i f) Source # | |
(Foldable i, Foldable (t f (Chain t i f))) => Foldable (Chain t i f) Source # | |
Defined in Data.HFunctor.Chain fold :: Monoid m => Chain t i f m -> m # foldMap :: Monoid m => (a -> m) -> Chain t i f a -> m # foldr :: (a -> b -> b) -> b -> Chain t i f a -> b # foldr' :: (a -> b -> b) -> b -> Chain t i f a -> b # foldl :: (b -> a -> b) -> b -> Chain t i f a -> b # foldl' :: (b -> a -> b) -> b -> Chain t i f a -> b # foldr1 :: (a -> a -> a) -> Chain t i f a -> a # foldl1 :: (a -> a -> a) -> Chain t i f a -> a # toList :: Chain t i f a -> [a] # null :: Chain t i f a -> Bool # length :: Chain t i f a -> Int # elem :: Eq a => a -> Chain t i f a -> Bool # maximum :: Ord a => Chain t i f a -> a # minimum :: Ord a => Chain t i f a -> a # | |
(Traversable i, Traversable (t f (Chain t i f))) => Traversable (Chain t i f) Source # | |
Defined in Data.HFunctor.Chain | |
(Eq1 i, Eq1 (t f (Chain t i f))) => Eq1 (Chain t i f) Source # | |
(Ord1 i, Ord1 (t f (Chain t i f))) => Ord1 (Chain t i f) Source # | |
Defined in Data.HFunctor.Chain | |
(Functor i, Read1 (t f (Chain t i f)), Read1 i) => Read1 (Chain t i f) Source # | |
Defined in Data.HFunctor.Chain liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (Chain t i f a) # liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [Chain t i f a] # liftReadPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec (Chain t i f a) # liftReadListPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec [Chain t i f a] # | |
(Show1 (t f (Chain t i f)), Show1 i) => Show1 (Chain t i f) Source # | |
(Eq (i a), Eq (t f (Chain t i f) a)) => Eq (Chain t i f a) Source # | |
(Ord (i a), Ord (t f (Chain t i f) a)) => Ord (Chain t i f a) Source # | |
Defined in Data.HFunctor.Chain compare :: Chain t i f a -> Chain t i f a -> Ordering # (<) :: Chain t i f a -> Chain t i f a -> Bool # (<=) :: Chain t i f a -> Chain t i f a -> Bool # (>) :: Chain t i f a -> Chain t i f a -> Bool # (>=) :: Chain t i f a -> Chain t i f a -> Bool # | |
(Read (i a), Read (t f (Chain t i f) a)) => Read (Chain t i f a) Source # | |
(Show (i a), Show (t f (Chain t i f) a)) => Show (Chain t i f a) Source # | |
type C (Chain t i) Source # | |
Defined in Data.HFunctor.Chain |
unfoldChain :: forall t f (g :: Type -> Type) i. HBifunctor t => (g ~> (i :+: t f g)) -> g ~> Chain t i f Source #
rerollMF :: forall t f. Monoidal t => Chain t (I t) f ~> MF t f Source #
A type
is supposed to represent the successive application of
MF
tt
s to itself. rerollSF
takes an explicit Chain
of applications of
t
to itself and rolls it back up into an
.MF
t
rerollMF
=foldChain
nilMF
consMF
Because t
cannot be inferred from the input or output, you should call
this with -XTypeApplications:
rerollMF
@Comp
::Chain
CompIdentity
f a ->Free
f a
unrollingMF :: Monoidal t => MF t f <~> Chain t (I t) f Source #
A type
is supposed to represent the successive application of
MF
tt
s to itself. The type
is an actual concrete
ADT that contains successive applications of Chain
t (I
t) ft
to itself, and you can
pattern match on each layer.
unrollingMF
states that the two types are isormorphic. Use unrollMF
and rerollMF
to convert between the two.
appendChain :: forall t f. Monoidal t => t (Chain t (I t) f) (Chain t (I t) f) ~> Chain t (I t) f Source #
Chain1
A useful construction that works like a "non-empty linked list" of t
f
applied to itself multiple times. That is, it contains t f f
, t
f (t f f)
, t f (t f (t f f))
, etc, with f
occuring one or more
times. It is meant to be the same as
.SF
t
A
is explicitly one of:Chain1
t f a
f a
t f f a
t f (t f f) a
t f (t f (t f f)) a
- .. etc
Note that this is exactly the description of
. And that's "the
point": for all instances of SF
tSemigroupoidal
,
is
isomorphic to Chain1
t
(witnessed by SF
tunrollingSF
). That's big picture
of SF
: it's supposed to be a type that consists of all possible
self-applications of f
to t
.
Chain1
gives you a way to work with all
in a uniform way.
Unlike for SF
t
in general, you can always explicitly /pattern
match/ on a SF
t fChain1
(with its two constructors) and do what you please
with it. You can also construct Chain1
using normal constructors
and functions.
You can convert in between
and SF
t f
with Chain1
t funrollSF
and rerollSF
. You can fully "collapse" a
into an Chain1
t ff
with retract
, if t
is Semigroupoidal
; this could be considered
a fundamental property of semigroupoidal-ness.
See Chain
for a version that has an "empty" value.
This construction is inspired by iteratees and machines.
Instances
HBifunctor t => HFunctor (Chain1 t :: (k -> Type) -> k -> Type) Source # | |
HBifunctor t => Inject (Chain1 t :: (k -> Type) -> k -> Type) Source # | |
(HBifunctor t, Semigroupoidal t) => Interpret (Chain1 t) Source # | |
(Functor f, Functor (t f (Chain1 t f))) => Functor (Chain1 t f) Source # | |
(Foldable f, Foldable (t f (Chain1 t f))) => Foldable (Chain1 t f) Source # | |
Defined in Data.HFunctor.Chain fold :: Monoid m => Chain1 t f m -> m # foldMap :: Monoid m => (a -> m) -> Chain1 t f a -> m # foldr :: (a -> b -> b) -> b -> Chain1 t f a -> b # foldr' :: (a -> b -> b) -> b -> Chain1 t f a -> b # foldl :: (b -> a -> b) -> b -> Chain1 t f a -> b # foldl' :: (b -> a -> b) -> b -> Chain1 t f a -> b # foldr1 :: (a -> a -> a) -> Chain1 t f a -> a # foldl1 :: (a -> a -> a) -> Chain1 t f a -> a # toList :: Chain1 t f a -> [a] # null :: Chain1 t f a -> Bool # length :: Chain1 t f a -> Int # elem :: Eq a => a -> Chain1 t f a -> Bool # maximum :: Ord a => Chain1 t f a -> a # minimum :: Ord a => Chain1 t f a -> a # | |
(Traversable f, Traversable (t f (Chain1 t f))) => Traversable (Chain1 t f) Source # | |
Defined in Data.HFunctor.Chain | |
(Eq1 f, Eq1 (t f (Chain1 t f))) => Eq1 (Chain1 t f) Source # | |
(Ord1 f, Ord1 (t f (Chain1 t f))) => Ord1 (Chain1 t f) Source # | |
Defined in Data.HFunctor.Chain | |
(Functor f, Read1 (t f (Chain1 t f)), Read1 f) => Read1 (Chain1 t f) Source # | |
Defined in Data.HFunctor.Chain | |
(Show1 (t f (Chain1 t f)), Show1 f) => Show1 (Chain1 t f) Source # | |
(Eq (f a), Eq (t f (Chain1 t f) a)) => Eq (Chain1 t f a) Source # | |
(Ord (f a), Ord (t f (Chain1 t f) a)) => Ord (Chain1 t f a) Source # | |
Defined in Data.HFunctor.Chain | |
(Read (f a), Read (t f (Chain1 t f) a)) => Read (Chain1 t f a) Source # | |
(Show (f a), Show (t f (Chain1 t f) a)) => Show (Chain1 t f a) Source # | |
Generic (Chain1 t f a) Source # | |
type C (Chain1 t) Source # | |
Defined in Data.HFunctor.Chain | |
type Rep (Chain1 t f a) Source # | |
Defined in Data.HFunctor.Chain type Rep (Chain1 t f a) = D1 (MetaData "Chain1" "Data.HFunctor.Chain" "functor-combinators-0.1.1.0-inplace" False) (C1 (MetaCons "Done1" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (f a))) :+: C1 (MetaCons "More1" PrefixI False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (t f (Chain1 t f) a)))) |
unfoldChain1 :: forall t f (g :: Type -> Type). HBifunctor t => (g ~> (f :+: t f g)) -> g ~> Chain1 t f Source #
unrollingSF :: forall t f. (Semigroupoidal t, Functor f) => SF t f <~> Chain1 t f Source #
A type
is supposed to represent the successive application of
SF
tt
s to itself. The type
is an actual concrete ADT that contains
successive applications of Chain1
t ft
to itself, and you can pattern match on
each layer.
unrollingSF
states that the two types are isormorphic. Use unrollSF
and rerollSF
to convert between the two.
appendChain1 :: forall t f. (Semigroupoidal t, Functor f) => t (Chain1 t f) (Chain1 t f) ~> Chain1 t f Source #
Chain1
is a semigroup with respect to t
: we can "combine" them in
an associative way.
Since: 0.1.1.0
Matchable
splittingChain1 :: forall t f. (Matchable t, Functor f) => Chain1 t f <~> t f (Chain t (I t) f) Source #
splitChain1 :: forall t f. Matchable t => Chain1 t f ~> t f (Chain t (I t) f) Source #
The "forward" function representing splittingChain1
. Provided here
as a separate function because it does not require
.Functor
f