
On Thu, Dec 23, 2010 at 5:25 PM, Stephen Tetley
On 23 December 2010 21:43, Mario Blažević
wrote: Why are Cofunctor and Comonad classes not a part of the base library? [SNIP] Later on I found that this question has been raised before by Conal Elliott, nearly four years ago.
http://www.haskell.org/pipermail/libraries/2007-January/006740.html
From a somewhat "philistine" persepective, that Conal's question went unanswered says something:
"Does anyone have useful functionality to go into a Cofunctor module (beyond the class declaration)?"
Successful post-H98 additions to Base (Applicative, Arrows, ...) brought a compelling programming style with them. For Comonads, Category-extras does define some extra combinators but otherwise they have perhaps seemed uncompelling.
As it happens, there actually is a significant programming style to go with "cofunctors". There's also a reason why it may not seem compelling to Haskell programmers, which I will illustrate with an analogy to other programming languages: Consider the problem of variance in a language with a subtyping relation and optionally mutable references. A subtype relationship A <: B can be viewed as an implicit conversion operator from A to B. Therefore, if you have a read-only reference to something of type A, you can create a read-only reference to something of type B. This can be seen as analogous to mapping the implicit conversion function over the identity functor applied to type A. On the other hand, what if you have a mutable reference to something of type A? You can't assign something of type B to it, because anything reading from the reference will receive a B, and there's no implicit conversion from B to A. However, if you instead have a mutable reference to something of type B, you can indeed assign something of type A to it using the implicit conversion. This is likewise analogous to mapping the conversion over an identity "cofunctor". In other words, contravariant functors naturally describe concepts like destructive assignment, pushing values into a "data sink" of some sort, etc. The simplest example of a potential contravariant functor in Haskell would be (-> r), i.e., a flipped version of the basic Reader functor (e ->). Similarly, assigning to an IORef, partially applied to the reference itself, gives the type (a -> IO ()), which is a special case of the flipped Reader. - C.