Search code examples
haskellcomonad

Understanding Comonad's <$$>


Given the following from fp-course:

class Functor f where
  (<$>) ::
    (a -> b)
    -> f a
    -> f b

class Functor f => Extend f where
  (<<=) ::
    (f a -> b)
    -> f a
    -> f b

I defined <$$> as so:

(<$$>) ::
  Comonad f =>
  (a -> b)
  -> f a
  -> f b
(<$$>) f fa = f <$> fa

However, I'm interested to know if there's another way to implement <$$> without using <$>. Is there? If so, please show it!


Solution

  • You need the extract method of Comonad; Extend isn't enough to get away without fmap.

    (<$$>)
      :: Comonad f
      => (a -> b)
      -> f a
      -> f b
    f <$$> w = f . extract <<= w
    

    This is basically how liftW is implemented in Control.Comonad.

    Note also that you need <<= (or extend); extract and duplicate aren't sufficient. The situation is similar to that of Bind and Monad; you can implement fmap using >>= and pure, but not using >>= alone and not using join and pure.