
On 2015-10-03 at 03:01:12 +0200, Henrik Nilsson wrote: [...]
Have you surveyed the actual number of books out there which show how to implement Monad instances and how many of them would be affected?
No. we have not. But ought not the burden of proof rest with those who are proposing a non-essential breaking change? If not, why not?
Well, afaik the books commonly used in teaching are largely based on Haskell 98 or Haskell 2010. ( IMO, the problem here is rather the expectation that the latest GHC would still provide a Haskell 2010 library environment, even though the few books based on GHC for the most part let the reader run GHC in default mode and mention neither `-XHaskell2010` nor `-package haskell2010`. And yes, GHC 7.10 effectively had to drop support for `-package haskell2010`. Otoh, There's several Linux distributions still stuck on GHC 7.6.3 (e.g. Debian & Ubuntu) or even older. Btw, would the concern be addressed if a future GHC would recover a legacy Haskell2010 library environment? ) All books I've looked at so far will undoubtedly have their examples defining `Monad` instances be broken under the next Haskell Report, even *without* the MRP which simplifies the Haskell Report and is surely more desirable from a pedagogical point of view as well. ---------------------------------------------------------------------------- For instance, in Graham Hutton's Book the section about defining Monad instances in chapter 10[1] is rather short (defining `Monad` instances is not an essential part of that book) and presents the Monads type-class literally as class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b and goes on to claim | Using this declaration, parsers and interactive programs can then be | made into instances of the class of monadic types, by defining the two | member functions in the appropriate manner: And this will clearly not apply anymore under the next Haskell Report. On the bright side, `fail` is not mentioned, so at least it won't break under the MonadFail change. ---- Richard Bird's "Thinking Functionally with Haskell" from 2014 sticks to Haskell2010, and presents the `Monad` class exactly like Graham's book (i.e. providing only `return` and `(>>=)`). Curiously, even though published in 2014, `Applicative` isn't mentioned anywhere in the book. In any case, this Book's `Monad`-instance examples will be broken as well under a new Haskell Report due to the AMP change. ---- Simon Thompson's "Haskell - the Craft of Functional Programming, 3ed" (2011), on the other hand presents the `Monad` class exactly as written into the Haskell 2010 Report, namely: class Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a (>>) :: m a -> m b -> m b fail :: String -> m a m >> k = m >>= \_ -> k fail s = error s Consequently, `Monad`-defining examples in that book break on accounts of both, AMP *and* MonadFail changes. ---- The "Real World Haskell" book predates Haskell 2010 by a few years but features the `Applicative` class. `Monad`-instance examples contained in the book break on accounts of AMP and MonadFail as well. ---- Miran Lipovaca's very popular "Learn You a Haskell for Great Good" (2011) book is written in a more casual style and targets mostly Haskell 2010. The `Monad` class is presented with the 4 methods according to the Haskell 2010 Report.[2] The `Applicative` class is mentioned and the missing superclass relationship is pointed out: | Shouldn't there be a class constraint in there along the lines of | `class (Applicative m) => Monad m where` so that a type has to be an | applicative functor first before it can be made a monad? Well, there | should, but when Haskell was made, it hadn't occured to people that | applicative functors are a good fit for Haskell so they weren't in | there. It's also noteworthy that the book has to explain why there are two different verbs for the same purpose: | The first function that the Monad type class defines is `return`. It's | the same as `pure`, only with a different name. Its type is `(Monad m) | => a -> m a`. It takes a value and puts it in a minimal default | context that still holds that value. In other words, it takes | something and wraps it in a monad. It always does the same thing as | the `pure` function from the `Applicative` type class, which means | we're already acquainted with `return`. We already used `return` when | doing I/O. We used it to take a value and make a bogus I/O action that | does nothing but yield that value. The `MonadFail` class, however, is neither mentioned nor anticipated. So LYAH will need to be updated as well regarding AMP and MonadFail induced breakages. ---- Finally, Alejandro Serrano Mena's more practical "Beginning Haskell" book also provides to the full Haskell 2010 `Monad` class definition. The `Applicative` class is described as well. However, the book was clearly written in the knowledge of the upcoming AMP: | If any Monad instance is also an instance of Functor, why is this | relation not shown in the declaration of those classes? This is a | historical accident, and you should expect Functor to soon become a | superclass of Monad . In the meantime, you should ensure that you have | an instance of Functor for each of your Monad instances: you can build | one easily using the aforementioned liftM function. as well as | The fact that Applicative does not appear as a superclass of Monad is | again a historical accident: the Monad concept was used widely much | earlier than the concept of Applicative . For compatibility reasons, | Monad hasn’t changed its definition to include any of Functor or | Applicative as superclasses. This will change soon, though, and the | full hierarchy Functor , then Applicative , then Monad will be | apparent in the type classes. But at the time of writing the MonadFail proposal couldn't be foreseen. ---------------------------------------------------------------------------- These may not be all the Haskell books out there, but these examples clearly show that we've already set a precedent with the AMP and the MonadFail proposal alone. There are a few other base-library transitions already happened or in mid-flight that have a similar effect on published books and materials which leave the boundaries of the Haskell 2010 Library Report. So if the primary argument is that published literature shouldn't get broken. Well, that's already happened. And there will unavoidably be incompatible changes between Haskell2010 and Haskell201x. The point of this Monad-of-no-return Proposal was to provide the formal basis to be able to write the AMP into the next upcoming Haskell Report in a sensible way (and I think we can all agree that this is the right thing to do as there is no good justification for including the `Monad(return)`-method in an Haskell Report integrating the AMP changes) However, one thing that seems to have been mostly ignored in this whole discussion so far is that just because the next Haskell Report anticipates the removal of `return` and `(>>)` as methods this doesn't mean that GHC's `base` library has to follow suit immediately! The proposal states that phase 2 can happen in GHC 8.2 *or later*. This could also mean e.g. GHC 8.4, GHC 8.8, or even GHC 9.0! This is very different from the AMP, MFP or FTP which are/were subject to a swift transition scheme with a rigid timeframe. Old code still overriding `return` will continue to compile (if it didn't break already for AMP/MFP/...) for as many years in GHC as desired. And code written against the new Haskell Report (especially when ignoring the existence of the `return`-method) would work just fine against GHC's `base` as well. So there's not that much immediate breakage due to MRP specifically after all. Regards, H.V.Riedel [1]: http://i.imgur.com/DyPTZml.png [2]: http://learnyouahaskell.com/a-fistful-of-monads#the-monad-type-class