<div dir="auto">This does not require a proposal--it merely replaces an inefficient implementation with an efficient one. If you're set up with Phabricator, just submit a patch. Otherwise, I'll be happy to do it for you.</div><div class="gmail_extra"><br><div class="gmail_quote">On Jan 19, 2017 12:22 AM, "Eric Mertens" <<a href="mailto:emertens@gmail.com">emertens@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"><div style="word-wrap:break-word">Hello,<div><br></div><div>Independently of a blog post I just noticed tonight on reddit, <a href="http://www.snoyman.com/blog/2017/01/follow-up-mapm" target="_blank">http://www.snoyman.<wbr>com/blog/2017/01/follow-up-<wbr>mapm</a> I observed a stack overflow in some code I was working with due to a recursive call inside the function argument of for_</div><div><br></div><div>The code was a more complicated version of:</div><div><br></div><div><font face="Courier New">go = for_ someMaybe $ \m -> m >> go</font></div><div><br></div><div>It was wrong in thinking that this could be efficient because there’s an extra operation to set the result to a (). I thought I might try working around this with the following code.</div><div><br></div><div><div><font face="Courier New">for__ :: (Applicative f, Foldable t) => t a -> (a -> f ()) -> f ()</font></div><div><font face="Courier New">for__ xs f = unApp (foldMap (coerce f) xs)</font></div><div><br></div></div><div><div><font face="Courier New">newtype App f = App { unApp :: f () }</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">instance Applicative f => Monoid (App f) where</font></div><div><font face="Courier New">  mempty                  = App (pure ())</font></div><div><font face="Courier New">  mappend (App x) (App y) = App (x *> y)</font></div></div><div><br></div><div>Unfortunately the instance for Foldable for Maybe does not provide an implementation of foldMap, it only provides foldl and foldr. This means that the derived foldMap implementation attempts to mappend an extra mempty because the default implementation of foldMap is</div><div><br></div><div><pre style="font-variant-ligatures:normal"><font face="Courier New"> <a name="m_-2393404565688521987_local-8214565720323889834"></a><a href="http://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Foldable.html#foldMap" style="text-decoration:none;border-bottom:1px solid rgb(238,232,213)" target="_blank"><span class="m_-2393404565688521987hs-identifier" style="color:rgb(7,54,66)">foldMap</span></a> <a name="m_-2393404565688521987_local-6989586621679114983"></a><a href="http://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Foldable.html#local-6989586621679114983" style="text-decoration:none;border-bottom:1px solid rgb(238,232,213)" target="_blank"><span class="m_-2393404565688521987hs-identifier" style="color:rgb(7,54,66)">f</span></a> <span class="m_-2393404565688521987hs-glyph" style="color:rgb(220,50,47)">=</span> <a href="http://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Foldable.html#foldr" style="text-decoration:none;border-bottom:1px solid rgb(238,232,213)" target="_blank"><span class="m_-2393404565688521987hs-identifier m_-2393404565688521987hs-var" style="color:rgb(7,54,66)">foldr</span></a> <span class="m_-2393404565688521987hs-special" style="color:rgb(220,50,47)">(</span><a href="http://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Base.html#mappend" style="text-decoration:none;border-bottom:1px solid rgb(238,232,213)" target="_blank"><span class="m_-2393404565688521987hs-identifier m_-2393404565688521987hs-var" style="color:rgb(7,54,66)">mappend</span></a> <a href="http://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Base.html#." style="text-decoration:none;border-bottom:1px solid rgb(238,232,213)" target="_blank"><span class="m_-2393404565688521987hs-operator m_-2393404565688521987hs-var" style="color:rgb(211,54,130)">.</span></a> <a href="http://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Foldable.html#local-6989586621679114983" style="text-decoration:none;border-bottom:1px solid rgb(238,232,213)" target="_blank"><span class="m_-2393404565688521987hs-identifier m_-2393404565688521987hs-var" style="color:rgb(7,54,66)">f</span></a><span class="m_-2393404565688521987hs-special" style="color:rgb(220,50,47)">)</span> <a href="http://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Base.html#mempty" style="text-decoration:none;border-bottom:1px solid rgb(238,232,213)" target="_blank"><span class="m_-2393404565688521987hs-identifier m_-2393404565688521987hs-var" style="color:rgb(7,54,66)">mempty</span></a></font></pre><div><br></div></div><div>With an explicit implementation of foldMap for the Maybe type (and maybe there are others that we’ve missed, for__ above can be stack efficient.</div><div><br></div><div><div>So I propose that we add an explicit implementation of foldMap to the Foldable Maybe instance</div><div><br></div><div><font face="Courier New">  foldMap _ Nothing  = mempty</font></div><div><font face="Courier New">  foldMap f (Just x) = f x</font></div><div><br></div><div><br></div><div>Best regards,</div></div><div>Eric Mertens</div></div><br>______________________________<wbr>_________________<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-<wbr>bin/mailman/listinfo/libraries</a><br>
<br></blockquote></div></div>