| Copyright | (c) Justin Le 2019 |
|---|---|
| License | BSD3 |
| Maintainer | [email protected] |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | None |
| Language | Haskell2010 |
Data.HFunctor.Chain
Description
This module provides an Interpretable 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
It 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 Methods 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 Methods 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 Methods 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 tts to itself. rerollSF takes an explicit Chain of applications of
t to itself and rolls it back up into an .MF t
rerollMF=foldChainnilMFconsMF
Because t cannot be inferred from the input or output, you should call
this with -XTypeApplications:
rerollMF@Comp::ChainCompIdentityf a ->Freef a
unrollingMF :: Monoidal t => MF t f <~> Chain t (I t) f Source #
A type is supposed to represent the successive application of
MF tts 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 Methods 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 Methods liftReadsPrec :: (Int -> ReadS a) -> ReadS [a] -> Int -> ReadS (Chain1 t f a) # liftReadList :: (Int -> ReadS a) -> ReadS [a] -> ReadS [Chain1 t f a] # liftReadPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec (Chain1 t f a) # liftReadListPrec :: ReadPrec a -> ReadPrec [a] -> ReadPrec [Chain1 t f a] # | |
| (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 tts 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