Copyright | (C) 2008-2013 Edward Kmett |
---|---|

License | BSD-style (see the file LICENSE) |

Maintainer | Edward Kmett <ekmett@gmail.com> |

Stability | provisional |

Portability | MPTCs, fundeps |

Safe Haskell | Safe |

Language | Haskell2010 |

Cofree comonads

## Synopsis

- data Cofree f a = a :< (f (Cofree f a))
- class (Functor f, Comonad w) => ComonadCofree f w | w -> f where
- unwrap :: w a -> f (w a)

- section :: Comonad f => f a -> Cofree f a
- coiter :: Functor f => (a -> f a) -> a -> Cofree f a
- coiterW :: (Comonad w, Functor f) => (w a -> f (w a)) -> w a -> Cofree f a
- unfold :: Functor f => (b -> (a, f b)) -> b -> Cofree f a
- unfoldM :: (Traversable f, Monad m) => (b -> m (a, f b)) -> b -> m (Cofree f a)
- hoistCofree :: Functor f => (forall x. f x -> g x) -> Cofree f a -> Cofree g a
- _extract :: Functor f => (a -> f a) -> Cofree g a -> f (Cofree g a)
- _unwrap :: Functor f => (g (Cofree g a) -> f (g (Cofree g a))) -> Cofree g a -> f (Cofree g a)
- telescoped :: Functor f => [(Cofree g a -> f (Cofree g a)) -> g (Cofree g a) -> f (g (Cofree g a))] -> (a -> f a) -> Cofree g a -> f (Cofree g a)
- telescoped_ :: Functor f => [(Cofree g a -> f (Cofree g a)) -> g (Cofree g a) -> f (g (Cofree g a))] -> (Cofree g a -> f (Cofree g a)) -> Cofree g a -> f (Cofree g a)
- shoots :: (Applicative f, Traversable g) => (a -> f a) -> Cofree g a -> f (Cofree g a)
- leaves :: (Applicative f, Traversable g) => (a -> f a) -> Cofree g a -> f (Cofree g a)

# Documentation

The `Cofree`

`Comonad`

of a functor `f`

.

*Formally*

A `Comonad`

`v`

is a cofree `Comonad`

for `f`

if every comonad homomorphism
from another comonad `w`

to `v`

is equivalent to a natural transformation
from `w`

to `f`

.

A `cofree`

functor is right adjoint to a forgetful functor.

Cofree is a functor from the category of functors to the category of comonads
that is right adjoint to the forgetful functor from the category of comonads
to the category of functors that forgets how to `extract`

and
`duplicate`

, leaving you with only a `Functor`

.

In practice, cofree comonads are quite useful for annotating syntax trees, or talking about streams.

A number of common comonads arise directly as cofree comonads.

For instance,

forms the a comonad for a non-empty list.`Cofree`

`Maybe`

is a product.`Cofree`

(`Const`

b)

forms an infinite stream.`Cofree`

`Identity`

describes a Moore machine with states labeled with values of type a, and transitions on edges of type b.`Cofree`

((->) b)'

Furthermore, if the functor `f`

forms a monoid (for example, by
being an instance of `Alternative`

), the resulting `Comonad`

is
also a `Monad`

. See
Monadic Augment and Generalised Shortcut Fusion by Neil Ghani et al., Section 4.3
for more details.

In particular, if `f a ≡ [a]`

, the
resulting data structure is a Rose tree.
For a practical application, check
Higher Dimensional Trees, Algebraically by Neil Ghani et al.

## Instances

ComonadTrans Cofree # | This is not a true |

Defined in Control.Comonad.Cofree | |

ComonadHoist Cofree # | |

ComonadEnv e w => ComonadEnv e (Cofree w) # | |

Defined in Control.Comonad.Cofree | |

ComonadStore s w => ComonadStore s (Cofree w) # | |

ComonadTraced m w => ComonadTraced m (Cofree w) # | |

Defined in Control.Comonad.Cofree | |

Functor f => ComonadCofree f (Cofree f) # | |

Defined in Control.Comonad.Cofree | |

Alternative f => Monad (Cofree f) # | |

Functor f => Functor (Cofree f) # | |

Alternative f => Applicative (Cofree f) # | |

Foldable f => Foldable (Cofree f) # | |

Defined in Control.Comonad.Cofree fold :: Monoid m => Cofree f m -> m # foldMap :: Monoid m => (a -> m) -> Cofree f a -> m # foldr :: (a -> b -> b) -> b -> Cofree f a -> b # foldr' :: (a -> b -> b) -> b -> Cofree f a -> b # foldl :: (b -> a -> b) -> b -> Cofree f a -> b # foldl' :: (b -> a -> b) -> b -> Cofree f a -> b # foldr1 :: (a -> a -> a) -> Cofree f a -> a # foldl1 :: (a -> a -> a) -> Cofree f a -> a # elem :: Eq a => a -> Cofree f a -> Bool # maximum :: Ord a => Cofree f a -> a # minimum :: Ord a => Cofree f a -> a # | |

Traversable f => Traversable (Cofree f) # | |

Eq1 f => Eq1 (Cofree f) # | |

Ord1 f => Ord1 (Cofree f) # | |

Defined in Control.Comonad.Cofree | |

Read1 f => Read1 (Cofree f) # | |

Defined in Control.Comonad.Cofree | |

Show1 f => Show1 (Cofree f) # | |

(Alternative f, MonadZip f) => MonadZip (Cofree f) # | |

Functor f => Comonad (Cofree f) # | |

ComonadApply f => ComonadApply (Cofree f) # | |

Distributive f => Distributive (Cofree f) # | |

Traversable1 f => Traversable1 (Cofree f) # | |

Foldable1 f => Foldable1 (Cofree f) # | |

Apply f => Apply (Cofree f) # | |

Functor f => Extend (Cofree f) # | |

Functor f => Generic1 (Cofree f :: Type -> Type) # | |

(Eq1 f, Eq a) => Eq (Cofree f a) # | |

(Typeable f, Data (f (Cofree f a)), Data a) => Data (Cofree f a) # | |

Defined in Control.Comonad.Cofree gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Cofree f a -> c (Cofree f a) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Cofree f a) # toConstr :: Cofree f a -> Constr # dataTypeOf :: Cofree f a -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (Cofree f a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Cofree f a)) # gmapT :: (forall b. Data b => b -> b) -> Cofree f a -> Cofree f a # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Cofree f a -> r # gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Cofree f a -> r # gmapQ :: (forall d. Data d => d -> u) -> Cofree f a -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Cofree f a -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Cofree f a -> m (Cofree f a) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Cofree f a -> m (Cofree f a) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Cofree f a -> m (Cofree f a) # | |

(Ord1 f, Ord a) => Ord (Cofree f a) # | |

(Read1 f, Read a) => Read (Cofree f a) # | |

(Show1 f, Show a) => Show (Cofree f a) # | |

Generic (Cofree f a) # | |

type Rep1 (Cofree f :: Type -> Type) # | |

Defined in Control.Comonad.Cofree type Rep1 (Cofree f :: Type -> Type) = D1 (MetaData "Cofree" "Control.Comonad.Cofree" "free-5.1-4UATSEhaXgTAvcVwsU7IL6" False) (C1 (MetaCons ":<" (InfixI RightAssociative 5) False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) Par1 :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (f :.: Rec1 (Cofree f)))) | |

type Rep (Cofree f a) # | |

Defined in Control.Comonad.Cofree type Rep (Cofree f a) = D1 (MetaData "Cofree" "Control.Comonad.Cofree" "free-5.1-4UATSEhaXgTAvcVwsU7IL6" False) (C1 (MetaCons ":<" (InfixI RightAssociative 5) False) (S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 a) :*: S1 (MetaSel (Nothing :: Maybe Symbol) NoSourceUnpackedness NoSourceStrictness DecidedLazy) (Rec0 (f (Cofree f a))))) |

class (Functor f, Comonad w) => ComonadCofree f w | w -> f where #

Allows you to peel a layer off a cofree comonad.

## Instances

ComonadCofree [] Tree # | |

Defined in Control.Comonad.Cofree.Class | |

ComonadCofree Maybe NonEmpty # | |

Functor f => ComonadCofree f (Cofree f) # | |

Defined in Control.Comonad.Cofree | |

Comonad w => ComonadCofree Identity (CoiterT w) # | |

(ComonadCofree f w, Monoid m) => ComonadCofree f (TracedT m w) # | |

Defined in Control.Comonad.Cofree.Class | |

ComonadCofree f w => ComonadCofree f (StoreT s w) # | |

Defined in Control.Comonad.Cofree.Class | |

ComonadCofree f w => ComonadCofree f (EnvT e w) # | |

Defined in Control.Comonad.Cofree.Class | |

ComonadCofree f w => ComonadCofree f (IdentityT w) # | |

Defined in Control.Comonad.Cofree.Class | |

(Functor f, Comonad w) => ComonadCofree f (CofreeT f w) # | |

Defined in Control.Comonad.Trans.Cofree | |

ComonadCofree (Const b :: Type -> Type) ((,) b) # | |

Defined in Control.Comonad.Cofree.Class |

coiterW :: (Comonad w, Functor f) => (w a -> f (w a)) -> w a -> Cofree f a #

Like coiter for comonadic values.

unfoldM :: (Traversable f, Monad m) => (b -> m (a, f b)) -> b -> m (Cofree f a) #

Unfold a cofree comonad from a seed, monadically.

hoistCofree :: Functor f => (forall x. f x -> g x) -> Cofree f a -> Cofree g a #

# Lenses into cofree comonads

telescoped :: Functor f => [(Cofree g a -> f (Cofree g a)) -> g (Cofree g a) -> f (g (Cofree g a))] -> (a -> f a) -> Cofree g a -> f (Cofree g a) #

Construct an `Lens`

into a

given a list of lenses into the base functor.
When the input list is empty, this is equivalent to `Cofree`

g`_extract`

.
When the input list is non-empty, this composes the input lenses
with `_unwrap`

to walk through the

before using
`Cofree`

g`_extract`

to get the element at the final location.

For more on lenses see the `lens`

package on hackage.

telescoped :: [Lens' (g (`Cofree`

g a)) (`Cofree`

g a)] -> Lens' (`Cofree`

g a) a

telescoped :: [Traversal' (g (`Cofree`

g a)) (`Cofree`

g a)] -> Traversal' (`Cofree`

g a) a

telescoped :: [Getter (g (`Cofree`

g a)) (`Cofree`

g a)] -> Getter (`Cofree`

g a) a

telescoped :: [Fold (g (`Cofree`

g a)) (`Cofree`

g a)] -> Fold (`Cofree`

g a) a

telescoped :: [Setter' (g (`Cofree`

g a)) (`Cofree`

g a)] -> Setter' (`Cofree`

g a) a

telescoped_ :: Functor f => [(Cofree g a -> f (Cofree g a)) -> g (Cofree g a) -> f (g (Cofree g a))] -> (Cofree g a -> f (Cofree g a)) -> Cofree g a -> f (Cofree g a) #

Construct an `Lens`

into a

given a list of lenses into the base functor.
The only difference between this and `Cofree`

g`telescoped`

is that `telescoped`

focuses on a single value, but this focuses on the entire remaining subtree.
When the input list is empty, this is equivalent to `id`

.
When the input list is non-empty, this composes the input lenses
with `_unwrap`

to walk through the

.`Cofree`

g

For more on lenses see the `lens`

package on hackage.

telescoped :: [Lens' (g (`Cofree`

g a)) (`Cofree`

g a)] -> Lens' (`Cofree`

g a) (`Cofree`

g a)

telescoped :: [Traversal' (g (`Cofree`

g a)) (`Cofree`

g a)] -> Traversal' (`Cofree`

g a) (`Cofree`

g a)

telescoped :: [Getter (g (`Cofree`

g a)) (`Cofree`

g a)] -> Getter (`Cofree`

g a) (`Cofree`

g a)

telescoped :: [Fold (g (`Cofree`

g a)) (`Cofree`

g a)] -> Fold (`Cofree`

g a) (`Cofree`

g a)

telescoped :: [Setter' (g (`Cofree`

g a)) (`Cofree`

g a)] -> Setter' (`Cofree`

g a) (`Cofree`

g a)

shoots :: (Applicative f, Traversable g) => (a -> f a) -> Cofree g a -> f (Cofree g a) #

A `Traversal'`

that gives access to all non-leaf `a`

elements of a

a, where non-leaf is defined as `Cofree`

g`x`

from `(x :< xs)`

where
`null xs`

is `False`

.

Because this doesn't give access to all values in the

,
it cannot be used to change types.`Cofree`

g

shoots :: Traversable g => Traversal' (Cofree g a) a

N.B. On GHC < 7.9, this is slightly less flexible, as it has to
use `null (toList xs)`

instead.

leaves :: (Applicative f, Traversable g) => (a -> f a) -> Cofree g a -> f (Cofree g a) #

A `Traversal'`

that gives access to all leaf `a`

elements of a

a, where leaf is defined as `Cofree`

g`x`

from `(x :< xs)`

where
`null xs`

is `True`

.

Because this doesn't give access to all values in the

,
it cannot be used to change types.`Cofree`

g

shoots :: Traversable g => Traversal' (Cofree g a) a

N.B. On GHC < 7.9, this is slightly less flexible, as it has to
use `null (toList xs)`

instead.