<div dir="ltr">I understand that you'd prefer it as a replacement for this plan than as a supplement, but I don't think that that would work all that well. We already have half a dozen combinators in Control.Monad generalized, more are generalizing in 7.10. e.g. We don't want to introduce a 'replicateA_' for instance as the pattern has been to generalize the existing 'M' combinators where possible.<div><br></div><div>What you propose would leave us paralyzed in an difficult to explain middle ground indefinitely.</div><div><br></div><div>As for making a thenM or thenDefault or thenDefaultByBind to make it easier to define (*>), I'm 100% on board with that.</div><div><br></div><div>-Edward</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 27, 2015 at 4:50 AM, Akio Takano <span dir="ltr"><<a href="mailto:tkn.akio@gmail.com" target="_blank">tkn.akio@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Thu, Nov 26, 2015 at 5:08 PM, Edward Kmett <<a href="mailto:ekmett@gmail.com">ekmett@gmail.com</a>> wrote:<br>
> On Thu, Nov 26, 2015 at 3:28 AM, Akio Takano <<a href="mailto:tkn.akio@gmail.com">tkn.akio@gmail.com</a>> wrote:<br>
>><br>
>> This is true, but I think it's much better to avoid breaking people's<br>
>> code in the first place. Also, since the breakage can be silent, one<br>
>> will not always be able to make a fix promptly.<br>
><br>
><br>
> We're not talking about making this change until we can get some warnings in<br>
> place.<br>
<br>
</span>I would appreciate such a warning. I was concerned because I didn't<br>
find a plan for one on the proposal page. In particular, neither the<br>
proposed -fwarn-mrp-compat flag nor the implemented<br>
-fwarn-noncanonical-monad-instances flag seemed to protect a<br>
programmer from the issue of silent performance regression, when there<br>
is no explicit definition for (*>) nor for (>>).<br>
<div><div class="h5"><br>
><br>
> That said, in the presence of some existing combinators that have already<br>
> been generalized from Monad to Applicative you may want to ensure that these<br>
> definitions have been fixed already.<br>
><br>
>> ><br>
>> > In situations where (<*>) is asymptotically more efficient than (>>=)<br>
>> > then<br>
>> > the default definition in terms of (<*>) wins.<br>
>><br>
>> You are right. I hadn't thought about this.<br>
>><br>
>> ><br>
>> > Right now, if you run through hackage there are lots of places where<br>
>> > (>>)<br>
>> > has been manually improved but the (*>) has not -- or vice versa. We<br>
>> > have<br>
>> > two places where people should apply an optimization and many have only<br>
>> > realized that they should optimize one or the other.<br>
>> ><br>
>> > The key here is to encourage folks to actually define (*>) when it<br>
>> > matters.<br>
>><br>
>> I understand this, but perhaps there is a way to achieve this without<br>
>> slowing down existing code. How about introducing a new warning<br>
>> (enabled with -Wall) that is triggered when a type satisfies the<br>
>> following 3 conditions?<br>
>><br>
>> 1. The type has a Monad instance and an Applicative instance declared<br>
>> in the same module, with the same set of constraints.<br>
>> 2. (*>) is not defined as (*>) = (>>). i.e. either it has a<br>
>> non-trivial definition or its definition is left out.<br>
>> 3. (>>) is not defined as (>>) = (*>). i.e. either it has a<br>
>> non-trivial definition or its definition is left out.<br>
>><br>
>> This way, people can be warned when (*>) and (>>) can share an<br>
>> implementation but they don't.<br>
><br>
><br>
> This is pretty much what Herbert has been working on, except with the<br>
> definition biased in favor of (>>) = (*>) being expected, and the other<br>
> becoming a warning as that definition blows up when and if we later move<br>
> (>>) out of the class.<br>
<br>
</div></div>Probably I wasn't clear, but I actually wanted to suggest a warning as<br>
a replacement for (the (>>)-related half of) MRP, not as a migration<br>
path to it. If the goal is to encourage people to have a good<br>
implementation for (*>), it may be achievable with just a warning,<br>
with no change to the class hierarchy.<br>
<br>
That said, I can imagine having a warning like this as a migration<br>
path. In that case we could provide a function like<br>
<br>
thenDefaultByBind :: (Monad m) => m a -> m b -> m b<br>
thenDefaultByBind a b = a >>= \_ -> b<br>
<br>
and give people an option to define<br>
<br>
(*>) = thenDefaultByBind<br>
<br>
in their Applicative instances.<br>
<br>
- Akio<br>
<br>
><br>
> -Edward<br>
</blockquote></div><br></div>