Open quchen opened 8 years ago
The redundant functions (like return
) are all well and good in an implementation such as GHC, but I think they should be struck from the Report. Let's design it like we should have from the beginning, cleanly. GHC could then include its non-conformance with this new standard as an infelicity. Perhaps GHC can even deprecate return
, but I don't have a problem with just living with the infelicity.
I agree, @goldfirere.
The Monad of no Return proposal was met with too much resistance (thanks to @hvr anyway!), so I think it’s off the table for now. For the next language standard however, I completely agree with @goldfirere: we should remove return
from the standard, and GHC is free to keep it as a GHC-ism.
One of the main points why I think we should even have a new standard, despite GHC being the only widely used compiler, is that we want to encourage new best practices for all users. Having redundant functions certainly does not help that cause. If implementations decide that it is useful to deviate from the standard for technical reasons (compatibility with old libraries) then that’s fine with me, but we would give a strong signal of the future direction of that almost-keyword. I suspect GHC will follow after a few releases, and even before that people on the IRC and on Reddit will tell others to avoid return
.
@strake MonadPlus is unfortunately not redundant: it adds laws that Alternative does not have.
Speaking of laws, maybe we should remove the right zero law of MonadPlus, but that’s something for a different discussion.
On 19/08/2016, David Luposchainsky notifications@github.com wrote:
@strake MonadPlus is unfortunately not redundant: it adds laws that Alternative does not have.
Ah, i see. But the methods are obsolete, yes? We could have class
MonadPlus
where empty >>= f = empty
.
Yes, that looks correct, @strake.
This is probably a minority view, but I'm not in favour of requiring users to implement Applicative in order to have a valid Monad instance. I understand the maths, but it makes teaching monads more convoluted than it needs to be.
Forgive me for riffing off in a strange direction, but I think we can have our cake and eat it too. Imagine we had this:
instance Functor m where
fmap :: (a -> b) -> m a -> m b
default fmap :: Monad m => (a -> b) -> m a -> m b
fmap = liftM
instance Functor m => Applicative m where
pure :: a -> m a
default pure :: Monad m => a -> m a
pure = return
(<*>) :: m (a -> b) -> m a -> m b
default (<*>) :: Monad m => m (a -> b) -> m a -> m b
(<*>) = ap
Now suppose we have a fully-defined instance Monad M
. Users need only write
instance Functor M
instance Applicative M
to get what they want. If only we had a -XAutoDeriveSuperclasses
, then these lines would come for free with instance Monad M
and we'd all go home early.
I know that this isn't the place to suggest such drastic measures, but we're so frustratingly close to being able to make the problem go away, I couldn't resist.
@zenzike I sympathise with your concern, but I believe that not requiring the Applicative instance does not solve the problem satisfactorily for everyone. In most (though admittedly not all) scenarios in which monads are introduced, one would also want to talk about applicative functors, either before or not long after discussing monads. In such cases, temporarily pretending Applicative didn't exist for the purpose of introducing monads would only delay the problem. (From your perspective, @goldfirere 's idea above might be an improvement, though it still would be necessary to make an aside on why it is necessary to add two instance declarations with no implementations, or to turn on a compiler extension.)
@goldfirere I had already considered the idea of default instances for Functor
and Applicative
, but I hadn't thought about having an -XAutoDeriveSuperclasses
as you suggest. I think this would alleviate my concerns if it were on by default (though the exact semantics of that extension don't seem trivial at first glance, and it's not clear that this is desirable). I don't think that this is a strange direction at all: we need to nail this if we'd like to keep the language accessible.
I don't think Haskell2020 necessarily has to include -XAutoDeriveSuperclasses
together with AMP. For teaching purposes, would it not be enough for GHC to support the former feature?
Good point @blamario . I wouldn't feel at all comfortable recommending discussion on -XAutoDeriveSuperclasses
here (although I do think it could be a well-specified feature -- but it would need time to mature).
On the other hand, my comment above also requires -XDefaultSignatures
, which I do think could be ready for standardization.
@goldfirere having default signatures for fmap
/return
/<*>
would be in conflict with all the
-Wnoncanonical-monad-instances
-Wnoncanonical-monadfail-instances
-Wnoncanonical-monoid-instances
compat warnings I put in place which aim at helping to detect and fix/change code to a situation where the implementations flow in a natural direction from superclasses to their subclasses via ordinary H2010 default implementations, and this is deliberately ruling out -XDefaultSignatures
based migration paths.
As having e.g. both return = pure
(in place since GHC 7.10) and pure = return
(which would not be possible with plain H2010) can result in annoyingly to debug cyclic definitions (or similarly for <>
/mappend
or *>
/>>
etc), and one of the reasons I state for moving return
(or >>
or mappend
or ...) out of the Monad
(or Monoid
) class to make such an undesired state unrepresentable in the first place.
That being said, we should have something like -XAutoDeriveSuperclasses
but I consider it a bad design to base its support for cases like AM(F)P or Monoid/MonadFail/Semigroup/... via -XDefaultSignatures
which reach for subclasses' implementations.
Refactoring type-classes is something that happens when libraries evolve and unfortunately something that Haskell doesn't yet provide a good built-in compatibility/migration story for, but I think there are other better designs possible for implicitly defining superclass instances when specifying e.g. Monad
/Monoid
/MonadFail
/... which would not require us to keep Monad.return
/Monad.(>>)
/Monoid.mappend
/Monad.fail
/... as a class methods around as well as rule out cyclic definitions between two redundant methods.
Specifically, since I consider it error-prone to have -XDefaultSignatures
refer to subclasses which is most often just a way of trading safety for convenience (and I'd go as far as making this a compile warning as I have been burned by this already a few times), I'd rather prefer a design where the subclass controls how to implement its superclasses, which would IMO allow to avoid the concerns I point out.
I can even think of schemes tailored to these simpler use-cases which would allow you to write H2010 Monad
definitions (for simple cases at least), and conveniently end up with a return
/>>
-free AMP-compliant instance hierarchy (assuming you don't have orphan instances lurking somewhere for Functor/Applicative/(MonadFail) which would then clash of course -- however, use-sites would still need to be upgraded to use e.g. MonadFail
and there's problematic cases for when a data-type has nested inner generic Monad -- think transformers
, but the -XDefaultSignatures
-based auto-instancing suffers from the same limitation anyway).
The canary RFC https://github.com/haskell/rfcs/pull/17 is on its way to become the first accepted and merged proposal. Once it flies through the complete process, I think this one could be next. Would anybody like to volunteer to add the actual Report modifications to this PR?
My opinion is that MonadFail and MonadOfNoReturn should be left as a separate proposal, if only for the sake of easier task breakdown.
To be honest, I'm having a hard time discussing AMP isolated from MRP as for me they're inseparable.
I know, but we shouldn't let the perfect be the enemy of the good. I think we can agree that bringing the report up to sync with GHC 8.0 would be a good thing (i.e., an improvement upon its current state), even if it leaves the pure
vs. return
issue in an ugly state.
Another argument in favour of baby steps is that MonadOfNoReturn is likely to present way more work overall. Not only is it more controversial, but the report text contains many occurrences of return
that must be sifted through. If the proposals are combined, they are less likely to be done.
What’s the challenge to having return = pure and leaving that report language as is? Just the proof reading ?
On Mon, Nov 19, 2018 at 9:11 AM Mario notifications@github.com wrote:
I know, but we shouldn't let the perfect be the enemy of the good. I think we can agree that bringing the report up to sync with GHC 8.0 would be a good thing (i.e., an improvement upon its current state), even if it leaves the pure vs. return issue in an ugly state.
Another argument in favour of baby steps is that MonadOfNoReturn is likely to present way more work overall. Not only is it more controversial, but the report text contains many occurrences of return that must be sifted through. If the proposals are combined, they are less likely to be done.
— You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/haskell/rfcs/pull/1#issuecomment-439905165, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQwrWMs31zH-7MfvKb3EWMF-JuOmd2ks5uwrv3gaJpZM4JS1Lq .
I think not doing MRP as part of AMP genuinely risks making an H2020 update out of date by construction, and that would be a bummer ..
as is, we should invest some effort into getting JOIN back into the monad type class in ghc to reconcile that bit too
On Mon, Nov 19, 2018 at 9:14 AM Carter Schonwald carter.schonwald@gmail.com wrote:
What’s the challenge to having return = pure and leaving that report language as is? Just the proof reading ?
On Mon, Nov 19, 2018 at 9:11 AM Mario notifications@github.com wrote:
I know, but we shouldn't let the perfect be the enemy of the good. I think we can agree that bringing the report up to sync with GHC 8.0 would be a good thing (i.e., an improvement upon its current state), even if it leaves the pure vs. return issue in an ugly state.
Another argument in favour of baby steps is that MonadOfNoReturn is likely to present way more work overall. Not only is it more controversial, but the report text contains many occurrences of return that must be sifted through. If the proposals are combined, they are less likely to be done.
— You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/haskell/rfcs/pull/1#issuecomment-439905165, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQwrWMs31zH-7MfvKb3EWMF-JuOmd2ks5uwrv3gaJpZM4JS1Lq .
Hi,
On 11/19/2018 08:24 PM, Carter Tazio Schonwald wrote:
I think not doing MRP as part of AMP genuinely risks making an H2020 update out of date by construction, and that would be a bummer ..
Many would disagree with this. MRP remains very controversial.
And a design with AMP but without MRP is not at all unreasonable. Not just for backwards compatibility (in a broad sense, not just code), but also looking forward as it (in principle) would allow for providing default instances of Functor and Applicative in terms of a monad instance. Which would be a jolly good thing in many ways, and is an application of extensions proposed for other reasons. After all, that would just amount to a generalisation of the existing possibility of providing default methods and giving programmers choice of which ones to provide, for example ...
as is, we should invest some effort into getting JOIN back into the monad type class in ghc to reconcile that bit too
... whether to define a monad through bind or join (which I definitely think should be possible).
In any case, without getting into a deep discussion about MRP at this point, there are definitely good reasons to discuss AMP and MRP separately, and there is no need suggest that the entire H2020 would be doomed unless MRP is adopted as part of AMP: regardless of what one think about AMP and MRP, there is a lot more to H2020.
Best,
/Henrik
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 contact the sender and delete the email and attachment.
Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham. Email communications with the University of Nottingham may be monitored where permitted by law.
What’s the challenge to having return = pure and leaving that report language as is? Just the proof reading ?
That would certainly be the easiest way to do it, but there should at least be some justification offered for having two names for the same thing. The report also contains sentences like
The type of
return
isMonad m => a -> m a
If we're not actually restricting the type of return
, this piece of text has to change. AMP alone doesn't need to answer these questions. At most, it needs to state that return a == pure a
is a law.
theres a simple reason: lots of code uses that name, and no code will fail to compile if return suddenly has Applicative f => a -> f a
as far as I'm concerned, theres zero controversy on this topic, all those second editions of haskell teaching material worked out well for their authors.
plus applicative do is a pretty sweet extension and we shouldnt choose a semantics for return that precludes a haskell 2020 implementation that isn't ghc from having that fancy feature :)
On Mon, Nov 19, 2018 at 8:39 PM Mario notifications@github.com wrote:
What’s the challenge to having return = pure and leaving that report language as is? Just the proof reading ?
That would certainly be the easiest way to do it, but there should at least be some justification offered for having two names for the same thing. The report also contains sentences like
The type of return is Monad m => a -> m a
If we're not actually restricting the type of return, this piece of text has to change. AMP alone doesn't need to answer these questions. At most, it needs to state that return a == pure a is a law.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/haskell/rfcs/pull/1#issuecomment-440105257, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQwu94wFYERz9kbdroNFqUI8_PEW_3ks5uw11AgaJpZM4JS1Lq .
Hi,
On 11/20/2018 05:23 AM, Carter Tazio Schonwald wrote:
as far as I'm concerned, theres zero controversy on this topic, all those second editions of haskell teaching material worked out well for their authors.
Well, there was a very extensive discussion about this a year or two ago, that made it very clear that many people found it very controversial. I have not seen any more extensive discussion since, so I so no reason to assume that the controversy is gone.
As to teaching, that is a very strong statement. There is a lot more to teaching than text books. Personally, I have, on numerous occasions, given introductions to monads without discussing applicatives, as monads is what was needed and there was no time at all for applicatives. (Try to cover functors, applicatives, and monads in a single lecture to an audience new to the topic.)
And at least one colleague of mine is the author of a best-seling Haskell textbook with decades of experience of teaching Haskell. In his (strong) opinion, teaching monads has become much more challenging with AMP, and further changes like MRP would not help at all.
plus applicative do is a pretty sweet extension and we shouldnt choose a semantics for return that precludes a haskell 2020 implementation that isn't ghc from having that fancy feature :)
Not having MRP does not mean not having applicatives. At all.
Best,
/Henrik
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 contact the sender and delete the email and attachment.
Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham. Email communications with the University of Nottingham may be monitored where permitted by law.
My experience of teaching cohorts of 200 students is that AMP has made it harder to teach monads and more frustrating to grasp. It is still a controversial topic and I have spoken to several colleagues at other universities who universally agree that it has made teaching harder. (I am also somewhat frustrated and apprehensive about having to teach Semiring before Monoid). The point is not “because maths”: we academics well understand the theory involved. The point is that we are deeply concerned for the masses of undergraduates who will struggle with yet one more hurdle.
With all due respect, this is a reason to use base / prelude as h2010, or write your own fork of ghc/prelude, not for deliberately deviating in a way that no compiler will sensibly choose to follow. Complain at the compiler, not at the standard.
This is a terrible reason to not fold in how we now know how to build better systems.
Applicative-do notation lets users write applicative computations in monadic style and then the compiler transforms the program into an applicative only computation, which (ignoring some subtleties around evaluation strictness) allows some very powerful applicative only patterns to be made usable in the more comprehensible do-notation style. I'd rather we ACTUALLY make effort to ensure a compliant compiler could choose to support applicative do as a strictly mechanical desugaring computation of programs that preserves well typed-ness, which NECESSITATES return :: Applicative f => a -> f a, OR a more needlessly complicated rewriting implementation
I'm hearing griping about choices that GHC will be doing irrespective of your personal feelings on the matter, and a failure to reflect these changes will just cement h2020 as something that ghc will not even implement/adhere to.
I support keeping Join in Monad because its the right thing, and means we can poke Richard and Stephanie to circle back on augmenting GHCs Role system so that GHC can reflect that design. Theres no planet where MRP will be inverted in any distribution of ghc that can be reasonably anticipated to exist.
On Tue, Nov 20, 2018 at 5:28 AM Nicolas Wu notifications@github.com wrote:
My experience of teaching cohorts of 200 students is that AMP has made it harder to teach monads and more frustrating to grasp. It is still a controversial topic and I have spoken to several colleagues at other universities who universally agree that it has made teaching harder. (I am also somewhat frustrated and apprehensive about having to teach Semiring before Monoid). The point is not “because maths”: we academics well understand the theory involved. The point is that we are deeply concerned for the masses of undergraduates who will struggle with yet one more hurdle.
— You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/haskell/rfcs/pull/1#issuecomment-440223208, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQwpc6dXdz9AylbFmWG_PQ9SSXvrrJks5uw9lngaJpZM4JS1Lq .
If I might make a modest proposal: what about removing the specifics of Monad
from the standard?
I see two reasons to include Monad
in the standard:
In order to describe the libraries. But, as is, the description of the libraries is a separable part of the report, and one might imagine making that section suggestive and/or an example instead of normative. Perhaps best in this regard is to make a set of minimal requirements of the libraries (i.e., that there exist a Num
class with a fromInteger :: Integer -> a
method, in order to define overloaded numbers), but not tightly specify the lot.
To define do
. But we can define do
without describing the details of Monad
. All we require is the desugaring into >>=
and >>
. (I don't mean to do this via rebindable syntax. The >>=
and >>
could be specified as regards to originating module.) I don't think there's even a language feature that directly invokes return
. (Monad comprehensions would, but I don't think they're standardized.)
If we remove the details of Monad
from the standard, then GHC can remain compliant, and other Haskell compilers may choose not to have Applicative
as a superclass of Monad
, or may decide that some other design (e.g. defaults) is better.
Hi,
With all due respect, this is a reason to use base / prelude as h2010, or write your own fork of ghc/prelude, not for deliberately deviating in a way that no compiler will sensibly choose to follow. Complain at the compiler, not at the standard.
This is a terrible reason to not fold in how we now know how to build better systems.
Note quite sure exactly what the "terrible reason" here is.
But no one has suggested a standard that would be DOA. The point is that there is plenty of scope for different designs, with various pros and cons, technical and not, and these pros and cons needs to be articulated clearly and concisely so that an informed choice can be made.
As to suggesting that teaching is done using a different version of the language, that is possible, of course (and attempts have been made), but carries with it its own problems. A very practical one is that it seems highly unlikely that a well-maintained teaching alternative would emerge. As to maintaining a fork of GHC in a teaching context, that does extremely infeasible once we consider it needs to keep working as the platforms and libraries keep evolving, and not only on some isolated lab computers, but also on students' computers.
Another point is that Haskell's success ultimately relies on a reasonably low barrier to entry. And in that context it is interesting to note many of my industrial contacts lament how difficult it is to hire Haskell programmers, and how even more difficult it is to hire Haskell programmers who do not overcomplicate things. To the point that in at least one recent case a company with a long-standing investment in Haskell felt compelled to switch to C++-.
But I digress.
So let's consider some solid technical arguments. Precluding support for some form of applicative do would certainly be a big cons. But:
we ACTUALLY make effort to ensure a compliant compiler could choose to support applicative do as a strictly mechanical desugaring computation of programs that preserves well typed-ness, which NECESSITATES return :: Applicative f => a -> f a, OR a more needlessly complicated rewriting implementation
It would be good to understand exactly why this is so.
Surely one could use "pure" in applicative do code? (Kind of similarly to how "returnA" is used in the Arrow do notation.) And using "pure" would arguably be a good thing as it clearly signals that a piece of code is applicative rather than monadic, which of course has implications as to where bound variables may occur and would likely also help with pinpointing errors due to misusing of variables?
Best,
/Henrik
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 contact the sender and delete the email and attachment.
Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham. Email communications with the University of Nottingham may be monitored where permitted by law.
Hi,
On 11/20/2018 03:48 PM, Richard Eisenberg wrote:
If I might make a modest proposal: what about removing the specifics of |Monad| from the standard?
Interesting thought, but as Monads have become a very fundamental aspect of Haskell (witness the logo! :-), I would worry about the the language fragmenting beyond repair if this was not part of the standard.
At least such a move would have to be very carefully considered, and not just from the point of view of the short-term impact on the report.
Best,
/Henrik
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 contact the sender and delete the email and attachment.
Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham. Email communications with the University of Nottingham may be monitored where permitted by law.
other Haskell compilers may choose not to have Applicative as a superclass of Monad
Yikes! That would mean that
foo :: Monad m => m Int
foo = pure 3
Would not be valid Haskell, according to the report. GHC already made this move and I am strongly aligned with what the proposed: "Whenever there's Monad code, you can use Functor/Applicative functions, without introducing an additional constraint."
The redundant functions (like return) are all well and good in an implementation such as GHC, but I think they should be struck from the Report. Let's design it like we should have from the beginning, cleanly.
I am in favor of this instead. Strike return
from the report, consider a deprecation cycle for it in ghc. Or keep return
in the report for language backwards-compatibility with the previous report, but indicate in the report that it is a legacy artifact.
For this, the proposal says 'With the new hierarchy, the answer would always be “use the least restrictive one”.' This is ok, but what would be better is to have an actual deprecation cycle, so that we eventually arrive at always using fmap
, and having liftA
and liftM
not exist anymore, etc.
As for the inconvenience of having to define instances, I think requiring users to use explicit definitions comparable to fmapDefault
is not so bad.
instance Functor F where
fmap = ...
instance Applicative F where
pure = ...
(<*>) = apMonadDefault
instance Monad F where
join = ...
instance Functor G where
fmap = fmapMonadDefault
instance Applicative G where
pure = ...
(<*>) = apMonadDefault
instance Monad F where
(>>=) = ...
A code linter could check to make sure you're not using fmapMonadDefault
to define fmap cyclically (since the default impl of >>=
is in terms of fmap
and join
, and fmapMonadDefault f m = m >>= pure . f
).
I would prefer (<*>) = apMonadDefault
to be implicit, but I understand if there are reasons not to do so.
Good points dan.
I guess we’re going to have to layout the landscape of possible edits and bring the decision before the full language committee.
I would like to remind folks that in some directions we have no authority over the decision making over CLC and GHC. It’s a partnership.
On Tue, Nov 20, 2018 at 11:45 AM Dan Burton notifications@github.com wrote:
other Haskell compilers may choose not to have Applicative as a superclass of Monad
Yikes! That would mean that
foo :: Monad m => m Int foo = pure 3
Would not be valid Haskell, according to the report. GHC already made this move and I am strongly aligned with what the proposed: "Whenever there's Monad code, you can use Functor/Applicative functions, without introducing an additional constraint."
The redundant functions (like return) are all well and good in an implementation such as GHC, but I think they should be struck from the Report. Let's design it like we should have from the beginning, cleanly.
I am in favor of this instead. Strike return from the report, consider a deprecation cycle for it in ghc. Or keep return in the report for language backwards-compatibility with the previous report, but indicate in the report that it is a legacy artifact.
For this, the proposal says 'With the new hierarchy, the answer would always be “use the least restrictive one”.' This is ok, but what would be better is to have an actual deprecation cycle, so that we eventually arrive at always using fmap, and having liftA and liftM not exist anymore, etc.
As for the inconvenience of having to define instances, I think requiring users to use explicit definitions comparable to fmapDefault is not so bad.
instance Functor F where fmap = ... instance Applicative F where pure = ... (<*>) = apMonadDefault instance Monad F where join = ...
instance Functor G where fmap = fmapMonadDefault instance Applicative G where pure = ... (<*>) = apMonadDefault instance Monad F where (>>=) = ...
A code linter could check to make sure you're not using fmapMonadDefault to define fmap cyclically (since the default impl of >>= is in terms of fmap and join, and fmapMonadDefault f m = m >>= pure . f ).
I would prefer (<*>) = apMonadDefault to be implicit, but I understand if there are reasons not to do so.
— You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/haskell/rfcs/pull/1#issuecomment-440343126, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQwoTa2QxiDBVwpY1bP8tNFkuqyiVLks5uxDHFgaJpZM4JS1Lq .
I'm glad that the passions have proven still alive, but can we please narrow the scope of this discussion a bit? This particular proposal is merely to add the Applicative
class to the report as a subclass of Functor
and superclass of Monad
. This does open further questions, particularly what to do with return
, but they can be resolved by follow-up proposals. If anybody feels strongly about this, here is a perfect chance to volunteer to write up both AMP and MRP or whatever and settle the issue the way you prefer.
So I'll repeat the question that started this round: will anybody volunteer to finalize this (AMP) proposal? The only reason not to do this is the one offered by goldfirere:
If I might make a modest proposal: what about removing the specifics of
Monad
from the standard?
I had considered this myself, but I feel that constructor type classes are such a core type of Haskell in practice that glossing over them would be highly misleading. I know that the language report is not the language reference, but this to me feels like cheating.
Still, I could be convinced. Can you clarify what you mean by originating module in
- To define
do
. But we can definedo
without describing the details ofMonad
. All we require is the desugaring into>>=
and>>
. (I don't mean to do this via rebindable syntax. The>>=
and>>
could be specified as regards to originating module.)
Do you mean that the do
notation would still desugar to Prelude.>>=
and Prelude.>>
?
Do you mean that the do notation would still desugar to
Prelude.>>=
andPrelude.>>
Yes. And I don't think we should fully strip Monad
from the report, but just specify minimal requirements. For example:
There exists a class Monad :: (* -> *) -> Constraint
(please let's not debate *
vs Type
here... but I'd be open to debating it elsewhere)
If Monad m
is satisfied, then (>>=) :: m a -> (a -> m b) -> m b
and (>>) :: m a -> m b -> m b
for any a
and b
.
I have thus tied Monad
to (>>=)
and (>>)
without stating the Monad
class nor even that (>>=) and
(>>)are members of that class. (Perhaps, for example, an implementation wants just to define
joinin the
Monadclass. Then
(>>=)and
(>>)` would just be top-level functions with constrained types.)
The minus to this approach is that it takes a fundamentally different philosophy to what it means to be "standards-compliant": With these new definitions, a standards-compliant implementation accepts all Haskell programs, but it does not necessarily reject all non-Haskell programs. Previously, the standard defined a concrete set of strings that were acceptable: anything in that set must be accepted and anything not in that set must be rejected.
I don't know if I like my new approach myself, but I thought it was worth pondering.
Back to the "design it like it should have been from the beginning" standpoint: I don't think we would have designed the Functor
/Applicative
/Monad
hierarchy as it exists in GHC today without some built-in defaulting or instance-template facility.
With these new definitions, a standards-compliant implementation accepts all Haskell programs, but it does not necessarily reject all non-Haskell programs.
I don't see why you're saying this. Consider this Haskell program:
f :: Monad m => m a -> m b -> m a
f = (<*)
According to these new definitions, both GHC 8.* and GHC 7.6 (before AMP) would be standard-compliant. They both define a Monad
class as well as (>>=)
and (>>)
of the prescribed types in Prelude. Yet this function definition is rejected by GHC 7.6 because its Monad
is not a subclass of Applicative
, not to mention Functor
.
Does the report specify (<*)
? My definitions didn't. By "Haskell program", I meant "program that corresponds to the definition of Haskell as in the report". Because (<*)
is not specified by the report, I'm not sure what your example is demonstrating...
A fair point. Let's add an
import Control.Applicative ((<*))
to the program, now it's not using anything out of Prelude except the Monad
constraint. Alternatively, try this example that uses nothing but Prelude:
myLiftM :: Monad m => (a -> b) -> m a -> m b
myLiftM = fmap
Unless you're suggesting removing the Functor
class from the Prelude, this program is valid iff Functor
is a superclass of Monad
. My previous example compiles iff Applicative
is a superclass of Monad
. I don't believe the validity of such elementary examples should be left up to every implementation's whim.
In my hypothetical vision, you're right that the validity of that example would be up to the implementation. Is that problematic? I agree that it is. Does that doom my vision? I suppose so.
I think this conversation is indicative of the fact that one wouldn't design the language accepted by today's GHC. That is, if you wanted to have deep class hierarchies, you would also design a way to manage that.
My attempt at such a design has languished at https://ghc.haskell.org/trac/ghc/wiki/InstanceTemplates. An alternative approach has languished at https://ghc.haskell.org/trac/ghc/wiki/IntrinsicSuperclasses. These were both written before today's proposals process. It would be interesting to propose one or both of these in that process today, but I don't have the bandwidth to take that on.
This is veering quite off-topic, but how do you feel about class morphisms? Do they stand a better chance of being implemented in GHC?
Sorry for the broadcast - I thought by submitting a comment against a commit of quchen's in his own repository I would be messaging only him. I did state I'm not a GitHub expert.
Rendered report is available at https://github.com/blamario/rfcs/blob/amp/report/report/haskell.pdf
Great!
On Sat, Dec 15, 2018 at 6:16 PM Mario notifications@github.com wrote:
Rendered report is available at https://github.com/blamario/rfcs/blob/amp/report/report/haskell.pdf
— You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/haskell/rfcs/pull/1#issuecomment-447604837, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAQwro9nBwPWBYTrQLVd0UomJCbBiZnks5u5YLPgaJpZM4JS1Lq .
There is an ongoing discussion on the libraries@ mailing list about changing the laws for some/many. If that happens in base then I would prefer to see the report carry the new definitions.
@blamario
If anybody feels strongly about this, here is a perfect chance to volunteer to write up both AMP and MRP or whatever and settle the issue the way you prefer.
I feel strongly enough about this to veto this PR, and do exactly as you suggest: Volunteer writing up both AMP+MRP as that's the way I prefer to settle this.
On the mailing list I've mentioned the possibility of do
using *>
instead of >>
. I may have suggested a scatalogical pronunciation of *>
rooted in its being constant and leaving the right-hand result, but that's somewhat less relevant.
I don't think there's any need to block this over the possibility of changing how do
-notation desugars, but I wanted to have mentioned it here so we can consider looking into it as a small, separate proposal. It would probably warrant a dry-run with a modest GHC extension if we went that way.
As far as I can tell, the semantic cost is that do
can now introduce an Applicative
constraint without introducing Monad
. I don't know how much additional burden that would create for teachers - personally I suspect not much compared to AMP though.
On the mailing list I've mentioned the possibility of
do
using*>
instead of>>
. I may have suggested a scatalogical pronunciation of*>
rooted in its being constant and leaving the right-hand result, but that's somewhat less relevant.I don't think there's any need to block this over the possibility of changing how
do
-notation desugars, but I wanted to have mentioned it here so we can consider looking into it as a small, separate proposal. It would probably warrant a dry-run with a modest GHC extension if we went that way.
Just to be clear, are you suggesting something different from the existing ApplicativeDo extension?
I am. ApplicativeDo
requires using <*>
where possible.
I'm suggesting that the existing do
translation use *>
where it would currently use >>
. No algorithmic change, just a different identifier emitted.
That would allow this to have an Applicative constraint instead of a Monad one:
do a
b
c
even where c
is not an invocation of pure.
It would do nothing to change this:
do f <- readFile "wherever"
putStr f
It's possible ApplicativeDo
works fine for the new use case in GHC 8.6.3. As it happens it doesn't in the 8.4 series! But my suggestion can be justified in terms of the AMP alone: that *>
is the new >>
.
This proposal is great. But, we can improve more.
Documents are important for beginner. GHC provides many information of Applicative
type class (e.g. law's name) by haddock comment but few information same as Haskell 2010 report for the Functor
/ Monad
classes.
I suggest
Functor
/ Monad
laws and show theseMonad
on the haddock comment same as Applicative
.
Straight adaption of the original proposal.
Rendered version of this proposal: https://github.com/quchen/rfcs/blob/amp/texts/0000-applicative-monad-superclass.rst