<p dir="ltr">No, we can't in general. With the exception of Control.Arrow (why that exception? No clue!) GHC's rewrite rules try very hard not to change the meaning of even bad user code. Yes, x <$ xs is supposed to be equivalent to fmap (const x) xs, and fmap is supposed to obey the functor laws. But neither of these is guaranteed, so a rewrite rule depending on these laws could change the meaning of user code.</p>
<div class="gmail_quote">On Apr 1, 2016 1:03 PM, "David Thomas" <<a href="mailto:davidleothomas@gmail.com">davidleothomas@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">If we provide (under whatever names) both the discard-value and the<br>
require-unit versions, then at least for the inlined case we could<br>
safely remove the overhead of void with a rewrite rule.<br>
<br>
On Fri, Apr 1, 2016 at 8:12 AM, Bryan Richter <<a href="mailto:b@chreekat.net">b@chreekat.net</a>> wrote:<br>
> On Fri, Apr 01, 2016 at 10:23:24AM -0400, davean wrote:<br>
>> On Fri, Apr 1, 2016 at 1:13 AM, Erik de Castro Lopo wrote:<br>
>><br>
>> > Which is the exact problem. I suspect that most people use `forM_`<br>
>> > as "assume the action returns unit" rather than "assume the return<br>
>> > value of the action is ignored".<br>
>> ><br>
>><br>
>> A review of my code shows I mostly use it as "assume the return value of<br>
>> the action is ignored".<br>
>><br>
>> Many things return data that is sometimes useful, but not always. Rarely do<br>
>> they have an '_' variant or the like to allow you to be more specific.<br>
><br>
> (emphasis added:)<br>
><br>
>> I wouldn't find it to be overly onerous to throw "void" in in those<br>
>> cases though.<br>
><br>
> The first email in this thread hinted at another possible solution,<br>
> with "unexpected behavior from... code that... has zero warning (even<br>
> with -Wall)."<br>
><br>
> Even if forM_ gets a new type, I don't think people will be much<br>
> assisted with the new message:<br>
><br>
>     Expected: IO ()<br>
>     Actual: IO (IO Int)<br>
><br>
> That message actually mixes two different problems. If the wisdom<br>
> becomes "throw a void on it", which I've already seen suggested a few<br>
> times, you easily get back to the original problem. Change the body of<br>
> the lambda to<br>
><br>
>     void $ maybe (HT.insert ht k v) (const $ abort k) <$> HT.lookup ht k<br>
>     ^^^^^^^<br>
><br>
> ...and now it *still* typechecks without warnings, but the original<br>
> problem remains.<br>
><br>
> Better, if possible, would be<br>
><br>
>     Warning: Discarded monadic value [in forM_]<br>
><br>
> Even that wouldn't catch my 'void $' above, but it also wouldn't<br>
> be indirectly *suggesting* it as a solution.<br>
><br>
> However, the thing Snoyberg raised about performance seems important.<br>
> Busting the stack while trying to throw away variables seems<br>
> unfortunate. Is Free the best counterexample to the "performance" of<br>
> `t a -> (a -> m ()) -> m ()`? Does Free really matter? It's not<br>
> exactly known for being a performant option.<br>
><br>
> _______________________________________________<br>
> Libraries mailing list<br>
> <a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
><br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div>