Haskell Code
I category theoretic form from here
class Functor w => Comonad w where (=>>) :: w a -> (w a -> b) -> w b coreturn :: w a -> a cojoin :: w a -> w (w a) x =>> f = fmap f (cojoin x)
Here is an instance of a celular automita:
instance Comonad U where cojoin a = U (tail $ iterate left a) a (tail $ iterate right a) coreturn (U _ b _) = b
Comonad for list:
A colist can't be empty:
data NonEmptyList a = One a | Many a (NonEmptyList a) map :: (a -> b) -> NonEmptyList a -> NonEmptyList b map f (One x) = One (f x) map f (Many x xs) = Many (f x) (map f xs) (++) :: NonEmptyList a -> NonEmptyList a -> NonEmptyList a One x ++ ys = Many x ys Many x xs ++ ys = Many x (xs ++ ys) tails :: NonEmptyList a -> NonEmptyList (NonEmptyList a) tails l@(One _) = One l tails l@(Many _ xs) = Many l (tails xs)
instance
instance Comonad NonEmptyList where coreturn (One x) = x coreturn (Many x xs) = x cojoin = tails
Or if you prefer haskel format:
Control.Comonad - Haskell Code
Methods
class Functor w => Comonad w where;
- extract :: w a -> aSource
- duplicate :: w a -> w (w a)Source
- extend :: (w a -> b) -> w a -> w bSource
Instances
Comonad Identity
- Monoid m => Comonad ((->) m)
- Comonad ((,) e)
- Comonad w => Comonad (IdentityT w)
Haskell Code (from here)
Monad | Comonad |
---|---|
I can put things in a context | I can extract things from a Context |
If I have a function which "computes values from inputs values which might change depending on the context": W a -> b, then I can use "values in context", W a, to return other "values in context", W b | |
-- the comonad operations
-- the dual of return or unit for monads
extract :: W a -> a
-- the dual of bind or flatMap for monads
cobind :: W a -> b -> W a -> W b
Scala
Forom scalaz
package scalaz trait Comonad[W[_]] extends Copointed[W] with Cojoin[W] trait ComonadLow { implicit def comonad[W[_]](implicit j: Cojoin[W], p: Copointed[W]): Comonad[W] = new Comonad[W] { def cojoin[A](a: W[A]) = j.cojoin(a) def fmap[A, B](a: W[A], f: A => B) = p.fmap(a, f) def copure[A](a: W[A]) = p.copure(a) } } object Comonad extends ComonadLow { import Cojoin._ import Copointed._ implicit def Tuple2Comonad[A] = comonad[({type λ[α]=(A, α)})#λ](Tuple2Cojoin, Tuple2Copointed) import java.util.Map.Entry implicit def MapEntryComonad[X] = comonad[({type λ[α]=Entry[X, α]})#λ](MapEntryCojoin, MapEntryCopointed) }; |