
Hi Dave On 5 Jan 2011, at 17:25, David Menendez wrote:
On Wed, Jan 5, 2011 at 8:05 AM, Conor McBride
wrote: On 5 Jan 2011, at 12:31, Bas van Dijk wrote:
On Wed, Jan 5, 2011 at 1:14 PM, Conor McBride
wrote: cabal install she
I knew about her but not that she supported default superclass instances. Nice!
She didn't. But she does now.
How does she handle multiple subclasses?
E.g., Functor can be defined in terms of Applicative (fmap = liftA) and in terms of Traversable (fmap = liftT). There are plenty of types which are both.
She lets you opt out. This is vital to any such default subclass scheme. I can write instance Monad Maybe where return = Just Nothing >>= _ = Nothing Just x >>= f = f x hiding instance Functor Maybe -- notation renegotiable and I'll get the Monad and Applicative instances, but not the Functor. Of course, if I don't otherwise provide a Functor instance, GHC will complain that it's missing. Crucially, however, I'm not forced to take the default. The ability to opt out of the default is crucial for several reasons: (1) You might have a choice of defaults, e.g. indeed, Functor from Applicative or Traversable, and you must choose at most one, even if they are extensionally equal. (2) You might have inherited a Functor from a library whose author did not know or care that it was Applicative (because it was obviously not a Monad, of course). You should not be prevented from declaring an Applicative instance by the prior Functor instance. (3) In the case of monad transformers, I might not want an instance Monad m => Functor (T m), especially if it prevents me from defining an instance Functor f => Functor (T f). (cf Oleg's example.) Please note that it's the cheapness of opting in, not requiring the user to assign the methods to their superclasses which assists with backward compatibility. It's been pointed out to me that one might consider class (A x, A y) => B x y where bthingy = .. instance A x where aring = .. ading = .. instance A y where aring = .. ading = .. with *two* default A instances. If we were to allow this, we should need to be able to switch at least one off in some instance B x x and, otherwise, to write stuff like instance B Int Bool where bthingy = .. instance A Int where aring = .. to be clear which A instance gets the overridden aring. At the moment, she doesn't handle this terribly well: you can have both defaults (unmodified) or neither. It's been helpful thinking about the problem in preprocessor terms, because it helps to figure out where the controls need to be. I hope this is progress, anyway. Cheers Conor