Can a monad be a comonad?

前端 未结 5 1962
孤独总比滥情好
孤独总比滥情好 2020-12-23 17:31

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

5条回答
  •  南方客
    南方客 (楼主)
    2020-12-23 18:05

    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/

提交回复
热议问题