Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a monad be a comonad?

I know what a monad is. I think I have correctly wrapped my mind around what a comonad is. (Or rather, what one is seems simple enough; the tricky part is comprehending what's useful about this...)

My question is: Can something be a monad and a comonad?

I foresee two possible answers:

  • Yes, this is common and widely useful.
  • No, they do such different jobs that there would be no reason to want something to be both.

So, which is it?

like image 750
MathematicalOrchid Avatar asked May 14 '13 19:05

MathematicalOrchid


1 Answers

The Cofree Comonad yields some data structures that are useful as Monads and Comonads both:

data Cofree f a = a :< f (Cofree f a) 

Every Cofree Comonad over an Alternative functor yields a Monad -- see the instance here:

http://hackage.haskell.org/packages/archive/free/3.4.1/doc/html/Control-Comonad-Cofree.html

instance Alternative f => Monad (Cofree f) where   return x = x :< empty   (a :< m) >>= k = case k a of                      b :< n -> b :< (n <|> fmap (>>= k) m) 

This gives us, e.g. nonempty lists as Monads and Comonads both (along with nonempty f-branching trees, etc).

Identity is not an alternative, but Cofree Identity yields an infinite stream, and we can in fact give a different monad instance to that stream:

http://hackage.haskell.org/packages/archive/streams/3.1/doc/html/Data-Stream-Infinite.html

data Stream a = a :> Stream a instance Comonad Stream where   duplicate = tails   extend f w = f w :> extend f (tail w)   extract = head  instance Monad Stream where   return = repeat   m >>= f = unfold (\(bs :> bss) -> (head bs, tail <$> bss)) (fmap f m) 

(note the functions above are not on lists but instead defined in the streams package).

Similarly the reader arrow is not an alternative, but Cofree ((->) r) yields a Moore machine, and Moore machines also are monads and comonads both:

http://hackage.haskell.org/packages/archive/machines/0.2.3.1/doc/html/Data-Machine-Moore.html

data Moore a b = Moore b (a -> Moore a b) instance Monad (Moore a) where   return a = r where r = Moore a (const r)   Moore a k >>= f = case f a of     Moore b _ -> Moore b (k >=> f)   _ >> m = m instance Comonad (Moore a) where   extract (Moore b _) = b   extend f w@(Moore _ g) = Moore (f w) (extend f . g) 

So what's the intuition behind all these examples? Well we get the comonadic operations for free. The monadic operations we get are all forms of diagonalization. With alternative we can <|> things together to "smush" the structure, and magic up "empty" things when we run out of structure to smush. This lets us work on finite cases. Lacking alternative we need to have an indefinite amount of structure, so that no matter how many "join" operations (which we can think of as splicing or substitution) that we make, there's always more room to place the spliced elements (like at the Hilbert Hotel: http://www.encyclopediaofmath.org/index.php/Hilbert_infinite_hotel).

Relatedly, every Comonad gives rise to a related Monad (although I consider this more a curiousity):

http://hackage.haskell.org/packages/archive/kan-extensions/3.1.1/doc/html/Control-Monad-Co.html

http://comonad.com/reader/2011/monads-from-comonads/

like image 191
sclv Avatar answered Sep 24 '22 00:09

sclv