Re: [Haskell-cafe] Functor => Applicative => Monad

On 22/12/10 19:17, John Smith wrote:
On 22/12/2010 19:03, Simon Marlow wrote:
On 14/12/2010 08:35, Isaac Dupree wrote:
On 12/14/10 03:13, John Smith wrote:
I would like to formally propose that Monad become a subclass of Applicative, with a call for consensus by 1 February. The change is described on the wiki at http://haskell.org/haskellwiki/Functor-Applicative-Monad_Proposal,
That page isn't written as a proposal yet, it's written as a bunch of ideas. I would be happy to see something along the lines of Bas van Dijk's work http://permalink.gmane.org/gmane.comp.lang.haskell.libraries/14740 .
This is a proposal with far-reaching consequences, and with several alternative designs. I'm not sure I understand all the tradeoffs. Some parts of the proposal are orthogonal to the rest (e.g. changing fmap to map), and should probably be considered separately.
Could someone please write a detailed proposal, enumerating all the pros and cons, and the rationale for this design compared to other designs?
Cheers, Simon
The wiki page was admittedly too broad of scope when I first wrote it, and it's getting broader with time.
The ticket at http://hackage.haskell.org/trac/ghc/ticket/4834 has patches for only one change, making Monad a subclass of Applicative. (I would update the description to make this clear, but I can't edit the ticket description, so this has been relegated to a comment.)
Dealing with one issue at a time is great. But even with this single change, we need to weight up the advantages and disadvantages - it's difficult to make an assessment without trawling through long email threads, and yet I don't want to let the proposal pass without comment. So it would help a lot if someone could take the time to explain the design space and the tradeoffs. I know for example I have lots of code that defines a Monad instance and doesn't need an Applicative instance, so this change will force me to jump through hoops that I don't need to. Cheers, Simon

On 22/12/2010 19:03, Simon Marlow wrote:
On 14/12/2010 08:35, Isaac Dupree wrote:
On 12/14/10 03:13, John Smith wrote:
I would like to formally propose that Monad become a subclass of Applicative, with a call for consensus by 1 February. The change is described on the wiki at http://haskell.org/haskellwiki/Functor-Applicative-Monad_Proposal,
That page isn't written as a proposal yet, it's written as a bunch of ideas. I would be happy to see something along the lines of Bas van Dijk's work http://permalink.gmane.org/gmane.comp.lang.haskell.libraries/14740 .
This is a proposal with far-reaching consequences, and with several alternative designs. I'm not sure I understand all the tradeoffs. Some parts of the proposal are orthogonal to the rest (e.g. changing fmap to map), and should probably be considered separately.
Could someone please write a detailed proposal, enumerating all the pros and cons, and the rationale for this design compared to other designs?
Cheers, Simon
I don't know exactly what the proposal process is, but what I'd like to see is something like the following: 1) "Subclasses" may declare default implementations of inherited methods. For example:
class Functor f => Applicative f where ... fmap f x = pure f <*> x
class Applicative f => Monad f where ... pure = return (<*>) = ap
2) Unless superclass instances are already in scope at declaration of an instance, an instance declaration implicitly also declares the superclass (and may also explicitly define functions in the superclass). For example:
instance Monad Maybe where return = Just (>>=) = ... fmap = ...
This declaration, in the absence of any explicit "instance Functor Maybe" and "instance Applicative Maybe", would implicitly define those instances as well, with the default implementations of fmap, pure, and <*> given. It would be a compile-time error to inherit multiple default definitions of a method, unless: a) There is a clear "shadowing" (eg, if the Monad class declaration included a default fmap, that would take precedence over the one in Applicative) b) The instance declaration explicitly defines the function, thus resolving the conflict. These changes, I believe, would make it possible to restructure the heirarchy with negligible impact on user code. The only potential impact I see so far would have to involve orphan instances, which are already considered risky/not a good idea. Specifically, if there were already an orphan Monad instance in one place and an orphan Applicative instance in another, the orphaned Applicative instance would become a duplicate instance which could potentially bite an end-user importing both modules. It would also be possible with fairly small user impact to move 'return' to Applicative, or even to a new 'Pointed' superclass of Applicative. To the end user, the type 'return :: Monad m => a -> m a' would still be valid, as would including "return" in a Monad instance declaration. Including 'pure' as well in Applicative (with defaults pure = return, return = pure) would allow old Applicative declarations to continue to work unchanged as well, though that obviously has the downside of introducing a new recursive default which is always potentially confusing to writers of new instances. -- James PS. Incidentally, I'd also prefer a class like the following instead of Applicative as it is now:
class Functor f => Monoidal f where return :: a -> f a (<*>) :: f a -> f b -> f (a,b)
But that would be a much more disruptive change.
participants (2)
-
mokus@deepbondi.net
-
Simon Marlow