Hello *,
Concluding AMP and MFP, We (David and I) proudly present you the final installment of the Monad trilogy: Monad of no `return` Proposal ============================= TLDR: To complete the AMP, turn `Monad(return)` method into a top-level binding aliasing `Applicative(pure)`. Current Situation ----------------- With the implementation of Functor-Applicative-Monad Proposal (AMP)[1] and (at some point) the MonadFail proposal (MFP)[2] the AMP class hierarchy becomes class Functor f where fmap :: (a -> b) -> f a -> f b class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b (*>) :: f a -> f b -> f b u *> v = … (<*) :: f a -> f b -> f a u <* v = … class Applicative m => Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a return = pure (>>) :: m a -> m b -> m b m >> k = … class Monad m => MonadFail m where fail :: String -> m a Consequently, the `Monad` class is left with a now redundant `return` method as a historic artifact, as there's no compelling reason to have `pure` and `return` implemented differently. Traditionally, `return` is often used where `pure` would suffice today, forcing a `Monad` constraint even if a weaker `Applicative` would have sufficed. As a result, language extensions like `ApplicativeDo`[3] have to rewrite `return` to weaken its `Monad m =>` constraint to `Applicative m =>` in order to benefit existing code at the cost of introducing magic behavior at the type level. Finally, this redundancy becomes even more significant when viewed in light of the renewed Haskell standardisation process[7]: The next Haskell Report will almost certainly incorporate the AMP (and MFP) changes, and there's no justification for the Report to retain `return` as a method of `Monad`. A good reason would have been to retain backward compatibility with Haskell 2010. However, as the AMP superclass hierarchy requires `Monad` instances to be accompanied by `Applicative` instances (which aren't part of Haskell 2010, c.f. [6]), backward compatibility with Haskell 2010 goes out the window when it comes to defining `Monad` instances (unless via use of `-XCPP` or similar). Consequently, meeting the high bar for a formal document such as the Haskell Report demands that `Monad` shall not carry a redundant `return` method that serves no purpose anymore. Moreover, getting `return` out of the way is desirable to facilitate standardising potential candidates such as the earlier mentioned `ApplicativeDo` in the future and avoids the technical debt incurred by keeping around this language wart. Proposed Change --------------- Remove `return` as a method from the `Monad` class and in its place define a top-level binding with the weaker `Applicative` typeclass constraint: -- | Legacy alias for 'pure' return :: Applicative f => a -> f a return = pure This allows existing code using `return` to benefit from a weaker typeclass constraint as well as cleaning the `Monad` class from a redundant method in the post-AMP world. A possible migration strategy is described further below. Compatibility Considerations ---------------------------- Generalizing the type signature of a function from a `Monad` constraint to its superclass `Applicative` doesn't cause new type-errors in existing code. However, moving a method to a top-level binding obviously breaks code that assumes `return` to be a class method. Foremost, code that defines `Monad` instances it at risk: ### Instance Definitions Code defining `return` as part of an instance definition breaks. However, we had the foresight to provide a default implementation in `base-4.8` for `return` so that the following represents a proper minimal instance definition post-AMP: instance Functor Foo where fmap g foo = … instance Applicative Foo where pure x = … a1 <*> a2 = … instance Monad Foo where m >>= f = … -- NB: No mention of `return` Consequently, it is possible to write forward-compatible instances that are valid under this proposal starting with GHC 7.10/`base-4.8`. Heuristically `grep`ing through Hackage source-code reveals a non-negligible number of packages defining `Monad` instances with explicit `return` definitions[4]. This has a comparable impact to the AMP, and similarly will require a transition scheme aided by compiler warnings. ### Module Import/Export Specifications A second source of incompatibility may be due to `import`s. Specifically module import that assert `return` to be a method of `Monad`, e.g.: import Control.Monad (Monad ((>>=), return)) or import Prelude hiding (Monad(..)) import Control.Monad (Monad(..)) as Monad f = Monad.return () The dual situation can occur when re-exporting `return` via module export specifications. However, given that `return` is exported by `Prelude` and the examples above are rather artificial, we don't expect this to be a major source of breakage in the case of `return`. In fact, a heuristic grep[5] over Hackage source-code revealed only 21 packages affected. ### Example for writing compatible code instance Functor Foo where fmap g foo = … instance Applicative Foo where pure x = … a1 <*> a2 = … instance Monad Foo where m >>= f = … #if !(MIN_VERSION_base(4,8,0)) return = pure #endif Migration Strategy ------------------ The migration strategy is straightforward: **Phase 1** *(GHC 8.0)*: Implement new warning in GHC which gets triggered when `Monad` instances explicitly override the default `return` method implementation. **Phase 2** *(GHC 8.2 or later)*: When we're confident that the majority of Hackage has reacted to the warning (with the help of Stackage actively pursuing maintainers to update their packages) we turn the `return` method into a top-level binding and remove the warning implemented in Phase 1 from GHC again. Discussion period ----------------- A discussion period of three weeks (until 2015-10-15) should be enough to allow everyone to chime in as well as leave enough time to make the required preparations for GHC 8.0 should this proposal pass as we hope. ---- [1]: https://wiki.haskell.org/Functor-Applicative-Monad_Proposal [2]: https://wiki.haskell.org/MonadFail_Proposal [3]: https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo [4]: https://gist.github.com/hvr/b0e34463d85b58f169d9 [5]: https://gist.github.com/hvr/afcd040783d980594883 [6]: https://ghc.haskell.org/trac/ghc/ticket/9590 [7]: https://mail.haskell.org/pipermail/haskell-prime/2015-September/003936.html -- _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries attachment0 (834 bytes) Download Attachment |
+1 on both the goal and the means of reaching it. That said, I suspect
the claim that "This has a comparable impact to the AMP" may be overly optimistic. Many Monad instances were Applicative instances before AMP, but I'd venture to guess that almost all Monad instances currently define return explicitly. On Thu, Sep 24, 2015 at 5:43 PM, Herbert Valerio Riedel <[hidden email]> wrote: > Hello *, > > Concluding AMP and MFP, We (David and I) proudly present you the final > installment of the Monad trilogy: > > > Monad of no `return` Proposal > ============================= > > TLDR: To complete the AMP, turn `Monad(return)` method into a > top-level binding aliasing `Applicative(pure)`. > > > Current Situation > ----------------- > > With the implementation of Functor-Applicative-Monad Proposal (AMP)[1] and > (at some point) the MonadFail proposal (MFP)[2] the AMP class hierarchy > becomes > > > class Functor f where > fmap :: (a -> b) -> f a -> f b > > > class Functor f => Applicative f where > pure :: a -> f a > (<*>) :: f (a -> b) -> f a -> f b > > (*>) :: f a -> f b -> f b > u *> v = … > > (<*) :: f a -> f b -> f a > u <* v = … > > > class Applicative m => Monad m where > (>>=) :: m a -> (a -> m b) -> m b > > return :: a -> m a > return = pure > > (>>) :: m a -> m b -> m b > m >> k = … > > > class Monad m => MonadFail m where > fail :: String -> m a > > > Consequently, the `Monad` class is left with a now redundant `return` > method as a historic artifact, as there's no compelling reason to > have `pure` and `return` implemented differently. > > Traditionally, `return` is often used where `pure` would suffice > today, forcing a `Monad` constraint even if a weaker `Applicative` > would have sufficed. > > As a result, language extensions like `ApplicativeDo`[3] have to > rewrite `return` to weaken its `Monad m =>` constraint to > `Applicative m =>` in order to benefit existing code at the cost > of introducing magic behavior at the type level. > > Finally, this redundancy becomes even more significant when viewed in > light of the renewed Haskell standardisation process[7]: The next > Haskell Report will almost certainly incorporate the AMP (and MFP) > changes, and there's no justification for the Report to retain > `return` as a method of `Monad`. A good reason would have been to > retain backward compatibility with Haskell 2010. However, as the AMP > superclass hierarchy requires `Monad` instances to be accompanied by > `Applicative` instances (which aren't part of Haskell 2010, c.f. [6]), > backward compatibility with Haskell 2010 goes out the window when it > comes to defining `Monad` instances (unless via use of `-XCPP` or > similar). Consequently, meeting the high bar for a formal document > such as the Haskell Report demands that `Monad` shall not carry a > redundant `return` method that serves no purpose anymore. Moreover, > getting `return` out of the way is desirable to facilitate > standardising potential candidates such as the earlier mentioned > `ApplicativeDo` in the future and avoids the technical debt incurred > by keeping around this language wart. > > > Proposed Change > --------------- > > Remove `return` as a method from the `Monad` class and in its place > define a top-level binding with the weaker `Applicative` typeclass > constraint: > > > -- | Legacy alias for 'pure' > return :: Applicative f => a -> f a > return = pure > > > This allows existing code using `return` to benefit from a weaker > typeclass constraint as well as cleaning the `Monad` class from a > redundant method in the post-AMP world. > > A possible migration strategy is described further below. > > > Compatibility Considerations > ---------------------------- > > Generalizing the type signature of a function from a `Monad` > constraint to its superclass `Applicative` doesn't cause new > type-errors in existing code. > > However, moving a method to a top-level binding obviously breaks code > that assumes `return` to be a class method. Foremost, code that > defines `Monad` instances it at risk: > > ### Instance Definitions > > Code defining `return` as part of an instance definition > breaks. However, we had the foresight to provide a default > implementation in `base-4.8` for `return` so that the following > represents a proper minimal instance definition post-AMP: > > > instance Functor Foo where > fmap g foo = … > > instance Applicative Foo where > pure x = … > a1 <*> a2 = … > > instance Monad Foo where > m >>= f = … > > -- NB: No mention of `return` > > > Consequently, it is possible to write forward-compatible instances > that are valid under this proposal starting with GHC 7.10/`base-4.8`. > > Heuristically `grep`ing through Hackage source-code reveals a > non-negligible number of packages defining `Monad` instances with > explicit `return` definitions[4]. This has a comparable impact to the > AMP, and similarly will require a transition scheme aided by compiler > warnings. > > ### Module Import/Export Specifications > > A second source of incompatibility may be due to > `import`s. Specifically module import that assert `return` to be a > method of `Monad`, e.g.: > > import Control.Monad (Monad ((>>=), return)) > > or > > import Prelude hiding (Monad(..)) > import Control.Monad (Monad(..)) as Monad > > f = Monad.return () > > The dual situation can occur when re-exporting `return` via module > export specifications. > > However, given that `return` is exported by `Prelude` and the examples > above are rather artificial, we don't expect this to be a major source > of breakage in the case of `return`. In fact, a heuristic grep[5] over > Hackage source-code revealed only 21 packages affected. > > ### Example for writing compatible code > > > instance Functor Foo where > fmap g foo = … > > instance Applicative Foo where > pure x = … > a1 <*> a2 = … > > instance Monad Foo where > m >>= f = … > > #if !(MIN_VERSION_base(4,8,0)) > return = pure > #endif > > > Migration Strategy > ------------------ > > The migration strategy is straightforward: > > **Phase 1** *(GHC 8.0)*: Implement new warning in GHC which gets > triggered when `Monad` instances explicitly override the > default `return` method implementation. > > **Phase 2** *(GHC 8.2 or later)*: When we're confident that the > majority of Hackage has reacted to the warning (with the help of > Stackage actively pursuing maintainers to update their packages) we > turn the `return` method into a top-level binding and remove the > warning implemented in Phase 1 from GHC again. > > > Discussion period > ----------------- > > A discussion period of three weeks (until 2015-10-15) should be enough > to allow everyone to chime in as well as leave enough time to make the > required preparations for GHC 8.0 should this proposal pass as we hope. > > ---- > > [1]: https://wiki.haskell.org/Functor-Applicative-Monad_Proposal > [2]: https://wiki.haskell.org/MonadFail_Proposal > [3]: https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo > [4]: https://gist.github.com/hvr/b0e34463d85b58f169d9 > [5]: https://gist.github.com/hvr/afcd040783d980594883 > [6]: https://ghc.haskell.org/trac/ghc/ticket/9590 > [7]: https://mail.haskell.org/pipermail/haskell-prime/2015-September/003936.html > > -- > > _______________________________________________ > Libraries mailing list > [hidden email] > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
"That" David is very +1 on this.
_______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by David Feuer
> El 24 sept 2015, a las 18:02, David Feuer <[hidden email]> escribió: > > +1 on both the goal and the means of reaching it. That said, I suspect > the claim that "This has a comparable impact to the AMP" may be overly > optimistic. Many Monad instances were Applicative instances before > AMP, but I'd venture to guess that almost all Monad instances > currently define return explicitly. > Right, I share this concern. This change breaks every package that defines a Monad (and comes close to turning every unmaintained package into a broken package. For what it's worth.). A couple questions: - Do you have any numbers (or grep heuristics) about the magnitude of breakage (esp. relative to AMP)? - What are the benefits of pulling "return" out instead of leaving it with the default "return = pure" and requiring the monad laws to hold? Is the rationale "since we're already willing to break things we shouldn't do half a job"? - Are there any (real-world) examples of people defining "pure" and "return" differently, e.g. for efficiency? - If we do decide to go forward with this, let's please get this in front of a wide audience asap! Tom >> On Thu, Sep 24, 2015 at 5:43 PM, Herbert Valerio Riedel <[hidden email]> wrote: >> Hello *, >> >> Concluding AMP and MFP, We (David and I) proudly present you the final >> installment of the Monad trilogy: >> >> >> Monad of no `return` Proposal >> ============================= >> >> TLDR: To complete the AMP, turn `Monad(return)` method into a >> top-level binding aliasing `Applicative(pure)`. >> >> >> Current Situation >> ----------------- >> >> With the implementation of Functor-Applicative-Monad Proposal (AMP)[1] and >> (at some point) the MonadFail proposal (MFP)[2] the AMP class hierarchy >> becomes >> >> >> class Functor f where >> fmap :: (a -> b) -> f a -> f b >> >> >> class Functor f => Applicative f where >> pure :: a -> f a >> (<*>) :: f (a -> b) -> f a -> f b >> >> (*>) :: f a -> f b -> f b >> u *> v = … >> >> (<*) :: f a -> f b -> f a >> u <* v = … >> >> >> class Applicative m => Monad m where >> (>>=) :: m a -> (a -> m b) -> m b >> >> return :: a -> m a >> return = pure >> >> (>>) :: m a -> m b -> m b >> m >> k = … >> >> >> class Monad m => MonadFail m where >> fail :: String -> m a >> >> >> Consequently, the `Monad` class is left with a now redundant `return` >> method as a historic artifact, as there's no compelling reason to >> have `pure` and `return` implemented differently. >> >> Traditionally, `return` is often used where `pure` would suffice >> today, forcing a `Monad` constraint even if a weaker `Applicative` >> would have sufficed. >> >> As a result, language extensions like `ApplicativeDo`[3] have to >> rewrite `return` to weaken its `Monad m =>` constraint to >> `Applicative m =>` in order to benefit existing code at the cost >> of introducing magic behavior at the type level. >> >> Finally, this redundancy becomes even more significant when viewed in >> light of the renewed Haskell standardisation process[7]: The next >> Haskell Report will almost certainly incorporate the AMP (and MFP) >> changes, and there's no justification for the Report to retain >> `return` as a method of `Monad`. A good reason would have been to >> retain backward compatibility with Haskell 2010. However, as the AMP >> superclass hierarchy requires `Monad` instances to be accompanied by >> `Applicative` instances (which aren't part of Haskell 2010, c.f. [6]), >> backward compatibility with Haskell 2010 goes out the window when it >> comes to defining `Monad` instances (unless via use of `-XCPP` or >> similar). Consequently, meeting the high bar for a formal document >> such as the Haskell Report demands that `Monad` shall not carry a >> redundant `return` method that serves no purpose anymore. Moreover, >> getting `return` out of the way is desirable to facilitate >> standardising potential candidates such as the earlier mentioned >> `ApplicativeDo` in the future and avoids the technical debt incurred >> by keeping around this language wart. >> >> >> Proposed Change >> --------------- >> >> Remove `return` as a method from the `Monad` class and in its place >> define a top-level binding with the weaker `Applicative` typeclass >> constraint: >> >> >> -- | Legacy alias for 'pure' >> return :: Applicative f => a -> f a >> return = pure >> >> >> This allows existing code using `return` to benefit from a weaker >> typeclass constraint as well as cleaning the `Monad` class from a >> redundant method in the post-AMP world. >> >> A possible migration strategy is described further below. >> >> >> Compatibility Considerations >> ---------------------------- >> >> Generalizing the type signature of a function from a `Monad` >> constraint to its superclass `Applicative` doesn't cause new >> type-errors in existing code. >> >> However, moving a method to a top-level binding obviously breaks code >> that assumes `return` to be a class method. Foremost, code that >> defines `Monad` instances it at risk: >> >> ### Instance Definitions >> >> Code defining `return` as part of an instance definition >> breaks. However, we had the foresight to provide a default >> implementation in `base-4.8` for `return` so that the following >> represents a proper minimal instance definition post-AMP: >> >> >> instance Functor Foo where >> fmap g foo = … >> >> instance Applicative Foo where >> pure x = … >> a1 <*> a2 = … >> >> instance Monad Foo where >> m >>= f = … >> >> -- NB: No mention of `return` >> >> >> Consequently, it is possible to write forward-compatible instances >> that are valid under this proposal starting with GHC 7.10/`base-4.8`. >> >> Heuristically `grep`ing through Hackage source-code reveals a >> non-negligible number of packages defining `Monad` instances with >> explicit `return` definitions[4]. This has a comparable impact to the >> AMP, and similarly will require a transition scheme aided by compiler >> warnings. >> >> ### Module Import/Export Specifications >> >> A second source of incompatibility may be due to >> `import`s. Specifically module import that assert `return` to be a >> method of `Monad`, e.g.: >> >> import Control.Monad (Monad ((>>=), return)) >> >> or >> >> import Prelude hiding (Monad(..)) >> import Control.Monad (Monad(..)) as Monad >> >> f = Monad.return () >> >> The dual situation can occur when re-exporting `return` via module >> export specifications. >> >> However, given that `return` is exported by `Prelude` and the examples >> above are rather artificial, we don't expect this to be a major source >> of breakage in the case of `return`. In fact, a heuristic grep[5] over >> Hackage source-code revealed only 21 packages affected. >> >> ### Example for writing compatible code >> >> >> instance Functor Foo where >> fmap g foo = … >> >> instance Applicative Foo where >> pure x = … >> a1 <*> a2 = … >> >> instance Monad Foo where >> m >>= f = … >> >> #if !(MIN_VERSION_base(4,8,0)) >> return = pure >> #endif >> >> >> Migration Strategy >> ------------------ >> >> The migration strategy is straightforward: >> >> **Phase 1** *(GHC 8.0)*: Implement new warning in GHC which gets >> triggered when `Monad` instances explicitly override the >> default `return` method implementation. >> >> **Phase 2** *(GHC 8.2 or later)*: When we're confident that the >> majority of Hackage has reacted to the warning (with the help of >> Stackage actively pursuing maintainers to update their packages) we >> turn the `return` method into a top-level binding and remove the >> warning implemented in Phase 1 from GHC again. >> >> >> Discussion period >> ----------------- >> >> A discussion period of three weeks (until 2015-10-15) should be enough >> to allow everyone to chime in as well as leave enough time to make the >> required preparations for GHC 8.0 should this proposal pass as we hope. >> >> ---- >> >> [1]: https://wiki.haskell.org/Functor-Applicative-Monad_Proposal >> [2]: https://wiki.haskell.org/MonadFail_Proposal >> [3]: https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo >> [4]: https://gist.github.com/hvr/b0e34463d85b58f169d9 >> [5]: https://gist.github.com/hvr/afcd040783d980594883 >> [6]: https://ghc.haskell.org/trac/ghc/ticket/9590 >> [7]: https://mail.haskell.org/pipermail/haskell-prime/2015-September/003936.html >> >> -- >> >> _______________________________________________ >> Libraries mailing list >> [hidden email] >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > _______________________________________________ > Libraries mailing list > [hidden email] > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by Herbert Valerio Riedel
>>>>> Herbert Valerio Riedel <[hidden email]> writes:
> TLDR: To complete the AMP, turn `Monad(return)` method into a > top-level binding aliasing `Applicative(pure)`. Very much +1. John _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
What about the derived functions in Control.Monad, such as liftM? Shall we similarly relax their constraints to Applicative and consider them "legacy"? (Did this already happen when I wasn't looking?)
On Thursday, September 24, 2015, John Wiegley <[hidden email]> wrote: >>>>> Herbert Valerio Riedel <<a href="javascript:;" onclick="_e(event, 'cvml', 'hvr@gnu.org')">hvr@...> writes: -- -- Dan Burton _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by Herbert Valerio Riedel
A conditional +1 from me, the condition being to allow the same
monad instance code to compile at least with GHC versions 7.8, 7.10, and 8.0 without any CPP directives. I think that can be accomplished by an extra clarification that the meaning of "override" in > **Phase 1** *(GHC 8.0)*: Implement new warning in GHC which gets > triggered when `Monad` instances explicitly override the > default `return` method implementation. does *not* include a re-definition of return = pure Yes, I realize this corner case would be a wart in the next language standard. We could fix that by disabling even this re-definition in case {#- LANGUAGE Haskell2020 #-} or equivalent is declared. Perhaps there should be two pragmas, {#- LANGUAGE Haskell2020+ #-} and {#- LANGUAGE Haskell2010-2020 #-}? _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by Dan Burton
Sadly liftM vs. liftA actually retains a useful distinction, one is a definition of fmap in terms of (>>=) and the other in terms of (<*>). `ap` gives a default definition of (<*>) in terms of (>>=), but if someone instead writes (<*>) = liftM2 id today, then erasing the distinction would turn that into a circular definition, transforming obviously-correct existant code silently into a _|_. -Edward On Thu, Sep 24, 2015 at 8:36 PM, Dan Burton <[hidden email]> wrote: What about the derived functions in Control.Monad, such as liftM? Shall we similarly relax their constraints to Applicative and consider them "legacy"? (Did this already happen when I wasn't looking?) _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by Herbert Valerio Riedel
I'm a rather enthusiastic +1 on this, given a sufficiently long time table for the switch! We ARE asking a lot of people to break code here. It does drastically reduce the amount of "magic" involved in the ApplicativeDo story and avoids enshrining the current historical artifact in a future Haskell report that includes the AMP. I'd also like to consider employing the exact same migration plan for (>>) at the same time. It is redundant with (*>), and the choice of which gets implemented in terms of the other introduces precisely the same set of issues. If we can do that then this would fix the remaining performance issues for mapM, letting us eventually remove that from Traversable as well, moving it to a top level alias in the same way -- maybe not until 8.8 or something, but it'd at least give us a roadmap to get there eventually. -Edward On Thu, Sep 24, 2015 at 5:43 PM, Herbert Valerio Riedel <[hidden email]> wrote: Hello *, _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
Yes, and I think there are still some more overly-specific things that come in here too, such as replicateM and filterM, which I don't think have been generalized yet. On Sep 24, 2015 10:40 PM, "Edward Kmett" <[hidden email]> wrote:
_______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
On 24/09/2015, David Feuer <[hidden email]> wrote:
> Yes, and I think there are still some more overly-specific things that come > in here too, such as replicateM and filterM, which I don't think have been > generalized yet. Someone posted a patch for that... https://ghc.haskell.org/trac/ghc/ticket/10168 _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by Edward Kmett-2
On 25.09.2015 04:40, Edward Kmett wrote:
> I'd also like to consider employing the exact same migration plan for > (>>) at the same time. It is redundant with (*>), and the choice of > which gets implemented in terms of the other introduces precisely the > same set of issues. If we can do that then this would fix the remaining > performance issues for mapM, letting us eventually remove that from > Traversable as well, moving it to a top level alias in the same way -- > maybe not until 8.8 or something, but it'd at least give us a roadmap to > get there eventually. +1 on bundling these changes. > On Thu, Sep 24, 2015 at 5:43 PM, Herbert Valerio Riedel <[hidden email] > <mailto:[hidden email]>> wrote: > > Hello *, > > Concluding AMP and MFP, We (David and I) proudly present you the final > installment of the Monad trilogy: > > > Monad of no `return` Proposal > ============================= > > TLDR: To complete the AMP, turn `Monad(return)` method into a > top-level binding aliasing `Applicative(pure)`. > > > Current Situation > ----------------- > > With the implementation of Functor-Applicative-Monad Proposal > (AMP)[1] and > (at some point) the MonadFail proposal (MFP)[2] the AMP class hierarchy > becomes > > > class Functor f where > fmap :: (a -> b) -> f a -> f b > > > class Functor f => Applicative f where > pure :: a -> f a > (<*>) :: f (a -> b) -> f a -> f b > > (*>) :: f a -> f b -> f b > u *> v = … > > (<*) :: f a -> f b -> f a > u <* v = … > > > class Applicative m => Monad m where > (>>=) :: m a -> (a -> m b) -> m b > > return :: a -> m a > return = pure > > (>>) :: m a -> m b -> m b > m >> k = … > > > class Monad m => MonadFail m where > fail :: String -> m a > > > Consequently, the `Monad` class is left with a now redundant `return` > method as a historic artifact, as there's no compelling reason to > have `pure` and `return` implemented differently. > > Traditionally, `return` is often used where `pure` would suffice > today, forcing a `Monad` constraint even if a weaker `Applicative` > would have sufficed. > > As a result, language extensions like `ApplicativeDo`[3] have to > rewrite `return` to weaken its `Monad m =>` constraint to > `Applicative m =>` in order to benefit existing code at the cost > of introducing magic behavior at the type level. > > Finally, this redundancy becomes even more significant when viewed in > light of the renewed Haskell standardisation process[7]: The next > Haskell Report will almost certainly incorporate the AMP (and MFP) > changes, and there's no justification for the Report to retain > `return` as a method of `Monad`. A good reason would have been to > retain backward compatibility with Haskell 2010. However, as the AMP > superclass hierarchy requires `Monad` instances to be accompanied by > `Applicative` instances (which aren't part of Haskell 2010, c.f. [6]), > backward compatibility with Haskell 2010 goes out the window when it > comes to defining `Monad` instances (unless via use of `-XCPP` or > similar). Consequently, meeting the high bar for a formal document > such as the Haskell Report demands that `Monad` shall not carry a > redundant `return` method that serves no purpose anymore. Moreover, > getting `return` out of the way is desirable to facilitate > standardising potential candidates such as the earlier mentioned > `ApplicativeDo` in the future and avoids the technical debt incurred > by keeping around this language wart. > > > Proposed Change > --------------- > > Remove `return` as a method from the `Monad` class and in its place > define a top-level binding with the weaker `Applicative` typeclass > constraint: > > > -- | Legacy alias for 'pure' > return :: Applicative f => a -> f a > return = pure > > > This allows existing code using `return` to benefit from a weaker > typeclass constraint as well as cleaning the `Monad` class from a > redundant method in the post-AMP world. > > A possible migration strategy is described further below. > > > Compatibility Considerations > ---------------------------- > > Generalizing the type signature of a function from a `Monad` > constraint to its superclass `Applicative` doesn't cause new > type-errors in existing code. > > However, moving a method to a top-level binding obviously breaks code > that assumes `return` to be a class method. Foremost, code that > defines `Monad` instances it at risk: > > ### Instance Definitions > > Code defining `return` as part of an instance definition > breaks. However, we had the foresight to provide a default > implementation in `base-4.8` for `return` so that the following > represents a proper minimal instance definition post-AMP: > > > instance Functor Foo where > fmap g foo = … > > instance Applicative Foo where > pure x = … > a1 <*> a2 = … > > instance Monad Foo where > m >>= f = … > > -- NB: No mention of `return` > > > Consequently, it is possible to write forward-compatible instances > that are valid under this proposal starting with GHC 7.10/`base-4.8`. > > Heuristically `grep`ing through Hackage source-code reveals a > non-negligible number of packages defining `Monad` instances with > explicit `return` definitions[4]. This has a comparable impact to the > AMP, and similarly will require a transition scheme aided by compiler > warnings. > > ### Module Import/Export Specifications > > A second source of incompatibility may be due to > `import`s. Specifically module import that assert `return` to be a > method of `Monad`, e.g.: > > import Control.Monad (Monad ((>>=), return)) > > or > > import Prelude hiding (Monad(..)) > import Control.Monad (Monad(..)) as Monad > > f = Monad.return () > > The dual situation can occur when re-exporting `return` via module > export specifications. > > However, given that `return` is exported by `Prelude` and the examples > above are rather artificial, we don't expect this to be a major source > of breakage in the case of `return`. In fact, a heuristic grep[5] over > Hackage source-code revealed only 21 packages affected. > > ### Example for writing compatible code > > > instance Functor Foo where > fmap g foo = … > > instance Applicative Foo where > pure x = … > a1 <*> a2 = … > > instance Monad Foo where > m >>= f = … > > #if !(MIN_VERSION_base(4,8,0)) > return = pure > #endif > > > Migration Strategy > ------------------ > > The migration strategy is straightforward: > > **Phase 1** *(GHC 8.0)*: Implement new warning in GHC which gets > triggered when `Monad` instances explicitly override the > default `return` method implementation. > > **Phase 2** *(GHC 8.2 or later)*: When we're confident that the > majority of Hackage has reacted to the warning (with the help of > Stackage actively pursuing maintainers to update their packages) we > turn the `return` method into a top-level binding and remove the > warning implemented in Phase 1 from GHC again. > > > Discussion period > ----------------- > > A discussion period of three weeks (until 2015-10-15) should be enough > to allow everyone to chime in as well as leave enough time to make the > required preparations for GHC 8.0 should this proposal pass as we hope. > > ---- > > [1]: https://wiki.haskell.org/Functor-Applicative-Monad_Proposal > [2]: https://wiki.haskell.org/MonadFail_Proposal > [3]: https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo > [4]: https://gist.github.com/hvr/b0e34463d85b58f169d9 > [5]: https://gist.github.com/hvr/afcd040783d980594883 > [6]: https://ghc.haskell.org/trac/ghc/ticket/9590 > [7]: > https://mail.haskell.org/pipermail/haskell-prime/2015-September/003936.html > > -- > > _______________________________________________ > Libraries mailing list > [hidden email] <mailto:[hidden email]> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > _______________________________________________ > Libraries mailing list > [hidden email] > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden [hidden email] http://www2.tcs.ifi.lmu.de/~abel/ _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by Herbert Valerio Riedel
On 09/24/2015 11:43 PM, Herbert Valerio Riedel wrote:
> Hello *, > +1, just a minor... nitpick, I guess: > > -- | Legacy alias for 'pure' > return :: Applicative f => a -> f a > return = pure > I propse to remove the "Legacy" designation (see below for reasoning). There should probably also be some reference to the Applicative type class, so I'd propose a wording more like: Alias for 'pure' in the 'Applicative' type class. Reasoning: I happen to rather like "return" for purely pedagogical purposes since it lets you pretend (as a sufficient-for-beginners approximation) that code in the do-notation in IO is imperative code and "return" is the usual name for what it does in that context. I think that has a certain value, but "Legacy" is quite off-putting. Presumably we aren't talking about removing "return" itself any time in the next, say, 5-10 years...? (That _would_ break a hell of a lot of code.) Anyway, just a (very) minor nitpick to consider. > However, given that `return` is exported by `Prelude` and the examples > above are rather artificial, we don't expect this to be a major source > of breakage in the case of `return`. In fact, a heuristic grep[5] over > Hackage source-code revealed only 21 packages affected. How many reverse dependencies do those packages have? (I.e. how many packages are going to require at least a version bump.) Regards, _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by Herbert Valerio Riedel
Hi,
At least with the current situation, it is possible (from my experience so far, but I don't claim to have tested extensively) to write code that works both with the old class hierarchy as well as the new: * Add an import Control.Applicative * Add an explicit method definition "return = pure" for Monad instances * Add Applicative to contexts in a few strategic places. That's a big plus in my books for people who for one reason or another would like to write code that works against an as broad range of different versions of the available Haskell tools as possible. On the other hand, I don't really understand the rationale: > Traditionally, `return` is often used where `pure` would suffice > today, forcing a `Monad` constraint even if a weaker `Applicative` > would have sufficed. > > As a result, language extensions like `ApplicativeDo`[3] have to > rewrite `return` to weaken its `Monad m =>` constraint to > `Applicative m =>` in order to benefit existing code at the cost > of introducing magic behavior at the type level. If code is genuinely applicative, why not encourage this to be clearly signalled by use of "pure" instead of "return"? Surely that would benefit long-term readability a lot more than supporting use of the "wrong" function. And as ApplicativeDo is a new extension, removing the magic so as to force such a change for code that really is applicative ought not to cause that much trouble for existing code. Thus, encourage (or force) people to say what they mean by using "pure" and "return" appropriately. I'm thus (very) unconvinced about the merits of this proposal. Best, /Henrik -- Henrik Nilsson School of Computer Science The University of Nottingham [hidden email] This message and any attachment are intended solely for the addressee and may contain confidential information. If you have received this message in error, please send it back to me, and immediately delete it. Please do not use, copy or disclose the information contained in this message or in any attachment. Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham. This message has been checked for viruses but the contents of an attachment may still contain software viruses which could damage your computer system, you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation. _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by Herbert Valerio Riedel
On 24/09/2015 22:43, Herbert Valerio Riedel wrote: > Hello *, > > Concluding AMP and MFP, We (David and I) proudly present you the final > installment of the Monad trilogy: > Very much +1, despite all the compat annoyances this is going to bring. -- Vincent _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
On 09/25/2015 01:14 PM, Vincent Hanquez wrote:
> > > On 24/09/2015 22:43, Herbert Valerio Riedel wrote: >> Hello *, >> >> Concluding AMP and MFP, We (David and I) proudly present you the final >> installment of the Monad trilogy: >> > Very much +1, despite all the compat annoyances this is going to bring. Ditto. _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries signature.asc (836 bytes) Download Attachment |
In reply to this post by David Feuer
David Feuer wrote:
> +1 on both the goal and the means of reaching it. That said, I suspect > the claim that "This has a comparable impact to the AMP" may be overly > optimistic. I want to echo this concern. In fact, the most common way of fixing code after the AMP proposal seems to have been to mechanically add instances instance Functor Foo where fmap = liftM instance Applicative Foo where pure = return (<*>) = ap whenever the compiler complained about a missing Applicative instance for a monad Foo. All those Applicative instances would have to be rewritten under the MRP proposal, and that task is not purely mechanical, since it involves moving existing code, so I'd say that the burden would be higher than after the AMP proposal. How many of those Applicative instances are there in hackage? Cheers, Bertram _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
In reply to this post by Herbert Valerio Riedel
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512 Enthusiastic +1 from me too, of course. - -- Alexander [hidden email] https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCgAGBQJWBTfiAAoJENQqWdRUGk8BU00QAMQfZo07CKomsjqcwNCDNqdm ifIhiz2kldR+A/gp6t/8IRf0RG3ZgZfwxhR5s/BWt7yV28napZfTMHPTfV8gE+bm V8AzvsXe/XLa9gTDyxqnY+ovYBDnEqmbX3SU03rRdtcN3jHiNuFkfIEIkRx6+HVx BKfoebxD7r1tgs/4nxjD8HljJEh6W8ux2Q8+sMWiCJEbVN5ixzTzGSk28vT2Ldyl GkoZJoXYM4K3WVCn23UmH9eokbdbnaCu2WRqzGgM7eQf+qqpouSjE3KRL5d9O/pE NMJIrNkC1L613GpfNeHLikOCKd78vbT0xnXyKHwAxv4Cr/7IZI3dyu+5MYwFntrY cdX7PgNQw7RN/tvZ63OOaRQEqvQfiOSdhPdFxAF5MabPNYMZMjIHqJuQseBaiUJf SWOU9oYNWW7XQVaQRVS5bP0KvRUhsA2+QXEd6pnhBEZ6u7qRQhaJowjca/A1TbB/ LHVG9nXE04fvc+CRkMK/xZEbuNWiMF0p4CZUiyeuAzhcZ9dge367ExfrTpTSLz8O Gfh04LgWs3rnvc3w8yhJJjcfsHhYZKQJMv40Rn8dgE/hyGFRpwQvBvFolZtFBZiS h6A/MyLDaSJCw3jwj+cU5PGLULGzdfNnTRlJ/jb4/CD2xUEOaQcAd+NvIJOlREcK RZBk4o5MU1aCsujOzjRd =VfnC -----END PGP SIGNATURE----- _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
Is the upgrade automatable with tooling that analyzes Haskell source code? If so can we provide an executable that will automatically upgrade packages?Pull requests could even be sent automatically. On Fri, Sep 25, 2015 at 5:02 AM, Alexander Berntsen <[hidden email]> wrote: -----BEGIN PGP SIGNED MESSAGE----- _______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
It *should* be possible to recognize return = pure On Sep 25, 2015 11:35 AM, "Greg Weber" <[hidden email]> wrote:
_______________________________________________ Libraries mailing list [hidden email] http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries |
Free forum by Nabble | Edit this page |