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:
So, which is it?
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With