
On 5/21/13 2:22 AM, Simon Peyton-Jones wrote:
| I'm generally a staunch advocate of backward compatibility. However, | these issues are ones where we've known the right answer for a long time | (unlike refactoring the numeric type class hierarchy), and we've simply | been unwilling to burn bridges in order to do the right thing. I love | Haskell, and I respect the haskell' committee, but I think it's time to | just burn it all down. ... | With all that has changed in the last 15 years, I think it's high time | to fork Haskell, tear off all the bandaids, and begin afresh.
I'm not sure what you are proposing, concrete, by "fork Haskell".
Concretely: I propose making a major library/Prelude revision in order apply the various changes we've talked about forever but never do anything about because of compatibility concerns. In particular, the goal is to remove warts and streamline things, not to make any "language" changes, per se. Backward compatibility should be of no concern in enacting this proposal (though, of course, flagrant/unnecessary changes should be avoided). Think of it like the Python-2 to Python-3 transition, or similar. Below is a tentative list of such changes. This is offered as the beginning of a discussion rather than a final proposal per se. As part of the proposal, we should solicit feedback from the community at large (not just on this list) as well as the haskell' committee in order to ensure that we do as much as we can to clean things up. In particular, it'd be good to assemble the list of complaints/proposals prior to trying to resolve the details of any particular one, similar to the haskell' process I suppose. * Applicative => Monad. * Unify pure/return. Depends on Applicative => Monad. * Add join method to Monad, with default definitions for join/(>>=). * Remove fail from Monad (add Monad => MonadFail, if desired). * Make the (<$) method of Functor more official. When starting up ghci-7.6.1, it only gives (<$) qualified as (GHC.Base.<$) * Replace Enum by type classes which do not require partial functions. (I have a more concrete proposal for this one, which I'll put on Hackage in the next week or so.) This isn't a hot topic like the others, but it's part of the general concern about having partial functions as standard/required parts of the language. * Remove from the Prelude things which are not required for resolving circularity. This is highly controversial, but I think it would help minimize future issues. If desired, in order to reduce imports, we could have an Interlude which serves the kitchen-sink role of the current Prelude but which requires an explicit import rather than being implicit like the Prelude is. * Remove the list-monomorphic versions of Foldable/Traversable functions. And/or export them from a separate PegagogicalHaskell module for learners to use, such that they do not materially affect intermediate/advanced Haskellers. * This is a bit off-proposal, but: do not have every Control.Monad.* module re-export Control.Monad. Modules like Control.Monad.Foo should only export Foo-specific things; if people want the general tools they can import Control.Monad itself. This is related to the pain of standardizing on Foldable/Traversable. * Clean up the Monoid class, add a Semigroup superclass, etc. There was a lot of discussion about this a while back. We came up with a fair solution, but it'd be nice to revisit the discussion and tighten things up while we're at it. I'm sure there are others I'm forgetting, which is why this is only a suggested list. One thing I thing we should _not_ do is try to tackle the numeric hierarchy (except perhaps for cleaning up non-numeric superclasses like Eq, Show, etc). As much as I'd like to see the numeric hierarchy improved, the design space is very large and the solution is far from clear. Attempting to address that issue now would derail the conversation from the above changes and the general goal of streamlining and removing warts.
I assume you guys have talked this to death, but is there no way to move on, while leaving a backward-compatible API?
The big problems with backward compatibility are (a) the standard type classes ---especially their superclass constraints---, and (b) the Prelude. Unfortunately, both of these are baked into the language in such a way that it's extremely difficult to change them without breaking things. One of the reasons the above changes haven't been made already is due to holding out hope for finding some way to make the changes without losing backward compatibility. However, we haven't found any good way to do that over the years, and there are no promising new leads at the moment. -- Live well, ~wren

On 05/24/2013 03:37 AM, wren ng thornton wrote:
On 5/21/13 2:22 AM, Simon Peyton-Jones wrote:
| I'm generally a staunch advocate of backward compatibility. However, | these issues are ones where we've known the right answer for a long time | (unlike refactoring the numeric type class hierarchy), and we've simply | been unwilling to burn bridges in order to do the right thing. I love | Haskell, and I respect the haskell' committee, but I think it's time to | just burn it all down. ... | With all that has changed in the last 15 years, I think it's high time | to fork Haskell, tear off all the bandaids, and begin afresh.
I'm not sure what you are proposing, concrete, by "fork Haskell".
* Unify pure/return. Depends on Applicative => Monad.
* Add join method to Monad, with default definitions for join/(>>=).
* Remove fail from Monad (add Monad => MonadFail, if desired).
* Make the (<$) method of Functor more official. When starting up ghci-7.6.1, it only gives (<$) qualified as (GHC.Base.<$)
* Replace Enum by type classes which do not require partial functions. (I have a more concrete proposal for this one, which I'll put on Hackage in the next week or so.) This isn't a hot topic like the others, but it's part of the general concern about having partial functions as standard/required parts of the language.
* Remove from the Prelude things which are not required for resolving circularity. This is highly controversial, but I think it would help minimize future issues. If desired, in order to reduce imports, we could have an Interlude which serves the kitchen-sink role of the current Prelude but which requires an explicit import rather than being implicit like the Prelude is.
* Remove the list-monomorphic versions of Foldable/Traversable functions. And/or export them from a separate PegagogicalHaskell module for learners to use, such that they do not materially affect intermediate/advanced Haskellers. (snip misc. other suggestions.)
I'm a bit surprised I haven't seen anyone mention it, but the Go community have a tool which can automate a lot of the tedium of API transitions: http://blog.golang.org/2011/04/introducing-gofix.html Maybe I'm missing something, but surely this kind of tool (a "hlint on steriods", I guess) could be written for many of the breaking changes that have been suggested in recent days on this list. Gofix specifically doesn't try to fix absolutely *everything*, but it fixes all the trivial stuff which is extremely annoying, but automatable, such as import lists, module/function renames, etc. (For a recent example, see "catch".) Heck, one could even imagine building in a "--future" mode into such a program to handle changes "one version ahead" during the deprecation cycle (which I assume we're not getting rid of). It could, for example, start issuing appropriate warnings for the Applicative => Monad transition. (Which would mean that we wouldn't need ad-hoc modifications to GHC to support such transitions.) AFAICT having such a tool in the Go ecosystem has been a huge boon, at least while the language and APIs were developing and in the transition from Go 1.0 to 1.1. Regards,

Dne 24.5.2013 04:57, Bardur Arantsson napsal(a): > On 05/24/2013 03:37 AM, wren ng thornton wrote: >> On 5/21/13 2:22 AM, Simon Peyton-Jones wrote: >>> | I'm generally a staunch advocate of backward compatibility. However, >>> | these issues are ones where we've known the right answer for a long time >>> | (unlike refactoring the numeric type class hierarchy), and we've simply >>> | been unwilling to burn bridges in order to do the right thing. I love >>> | Haskell, and I respect the haskell' committee, but I think it's time to >>> | just burn it all down. >>> ... >>> | With all that has changed in the last 15 years, I think it's high time >>> | to fork Haskell, tear off all the bandaids, and begin afresh. >>> >>> I'm not sure what you are proposing, concrete, by "fork Haskell". >> * Unify pure/return. Depends on Applicative => Monad. >> >> * Add join method to Monad, with default definitions for join/(>>=). >> >> * Remove fail from Monad (add Monad => MonadFail, if desired). >> >> * Make the (<$) method of Functor more official. When starting up >> ghci-7.6.1, it only gives (<$) qualified as (GHC.Base.<$) >> >> * Replace Enum by type classes which do not require partial functions. (I >> have a more concrete proposal for this one, which I'll put on Hackage in >> the next week or so.) This isn't a hot topic like the others, but it's >> part of the general concern about having partial functions as >> standard/required parts of the language. >> >> * Remove from the Prelude things which are not required for resolving >> circularity. This is highly controversial, but I think it would help >> minimize future issues. If desired, in order to reduce imports, we could >> have an Interlude which serves the kitchen-sink role of the current >> Prelude but which requires an explicit import rather than being implicit >> like the Prelude is. >> >> * Remove the list-monomorphic versions of Foldable/Traversable functions. >> And/or export them from a separate PegagogicalHaskell module for learners >> to use, such that they do not materially affect intermediate/advanced >> Haskellers. > (snip misc. other suggestions.) > > I'm a bit surprised I haven't seen anyone mention it, but the Go > community have a tool which can automate a lot of the tedium of API > transitions: > > http://blog.golang.org/2011/04/introducing-gofix.html > > Maybe I'm missing something, but surely this kind of tool (a "hlint on > steriods", I guess) could be written for many of the breaking changes > that have been suggested in recent days on this list. > > Gofix specifically doesn't try to fix absolutely *everything*, but it > fixes all the trivial stuff which is extremely annoying, but > automatable, such as import lists, module/function renames, etc. (For a > recent example, see "catch".) > > Heck, one could even imagine building in a "--future" mode into such a > program to handle changes "one version ahead" during the deprecation > cycle (which I assume we're not getting rid of). It could, for example, > start issuing appropriate warnings for the Applicative => Monad > transition. (Which would mean that we wouldn't need ad-hoc modifications > to GHC to support such transitions.) > > AFAICT having such a tool in the Go ecosystem has been a huge boon, at > least while the language and APIs were developing and in the transition > from Go 1.0 to 1.1. > > I'd also support the suggestion of making several changes at once, that solve many recurring problems. For me it's easier to make one big upgrade to my code once, than to make a small upgrade every now and then if the language changes in small steps. The idea of making an automated tool is really great, I was just thinking about something similar. Some changes would be really trivial, like adding "import Interlude". Some would be slightly more complex, like refactoring Monad instances into Applicative+Monad, but I believe it'd be very well possible. Best regards, Petr

On Fri, 2013-05-24 at 09:30 +0200, Petr Pudlák wrote:
Dne 24.5.2013 04:57, Bardur Arantsson napsal(a):
I'm a bit surprised I haven't seen anyone mention it, but the Go community have a tool which can automate a lot of the tedium of API transitions:
http://blog.golang.org/2011/04/introducing-gofix.html
Maybe I'm missing something, but surely this kind of tool (a "hlint on steriods", I guess) could be written for many of the breaking changes that have been suggested in recent days on this list.
Gofix specifically doesn't try to fix absolutely *everything*, but it fixes all the trivial stuff which is extremely annoying, but automatable, such as import lists, module/function renames, etc. (For a recent example, see "catch".)
Heck, one could even imagine building in a "--future" mode into such a program to handle changes "one version ahead" during the deprecation cycle (which I assume we're not getting rid of). It could, for example, start issuing appropriate warnings for the Applicative => Monad transition. (Which would mean that we wouldn't need ad-hoc modifications to GHC to support such transitions.)
AFAICT having such a tool in the Go ecosystem has been a huge boon, at least while the language and APIs were developing and in the transition from Go 1.0 to 1.1.
I'd also support the suggestion of making several changes at once, that solve many recurring problems. For me it's easier to make one big upgrade to my code once, than to make a small upgrade every now and then if the language changes in small steps.
The idea of making an automated tool is really great, I was just thinking about something similar. Some changes would be really trivial, like adding "import Interlude". Some would be slightly more complex, like refactoring Monad instances into Applicative+Monad, but I believe it'd be very well possible.
This has been coined on haskell-cafe some time ago as well, see [1] and [2]. Nicolas [1] http://www.haskell.org/pipermail/haskell-cafe/2013-May/108086.html [2] http://www.haskell.org/pipermail/haskell-cafe/2013-May/108087.html
participants (4)
-
Bardur Arantsson
-
Nicolas Trangez
-
Petr Pudlák
-
wren ng thornton