<div dir="ltr">+1.<br><br>I also remember this post by Neil Mitchell which seems appropriate: <a href="http://neilmitchell.blogspot.com/2008/12/mapm-mapm-and-monadic-statements.html">http://neilmitchell.blogspot.com/2008/12/mapm-mapm-and-monadic-statements.html</a>. He also uses the name "ignore" for your function.<br>
<br>Michael<br><br><div class="gmail_quote">On Wed, Jun 10, 2009 at 7:53 PM, Gwern Branwen <span dir="ltr"><<a href="mailto:gwern0@gmail.com">gwern0@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
-----BEGIN PGP SIGNED MESSAGE-----<br>
Hash: SHA512<br>
<br>
So while writing my wp-archivebot, I ran into the issue that forkIO<br>
requires IO () but returns IO ThreadId, and that many useful IO<br>
functions will return IO a instead of IO ().<br>
<br>
This forces some awkward contortions. Suppose I want to ping the<br>
WebCite website at a particular address, and this request makes<br>
WebCite archive a URL embedded in that address. Presumably I could<br>
venture into the depths of Network.HTTP to figure out how to ping an<br>
URL without also pulling down the server's HTML, but why do that when<br>
I already have obviously 'openURL :: String -> IO String'? Much<br>
easier to do something like 'openURL "<a href="http://webcite.org" target="_blank">webcite.org</a>" ++ foo ++ "other<br>
stuff" '.<br>
<br>
But my bot needs to handle quite a few URLs; one at a time, what with<br>
all the waits and timeouts, isn't going to hack it. So for a given<br>
link, I forkIO the openURL request. But of course, forkIO demands IO<br>
(), so I toss in a '>> return ()'. Fair enough.<br>
<br>
So I examine the performance, and it's still too slow. Recent Changes<br>
has hundreds of different pages a minute. I'd better fork each page<br>
(and then fork for each link). But wait, all those forkIOs are<br>
returning IO ThreadIds, and my top-level forkIO call demands IO ()...<br>
So another >> return (). At this point, the code is starting to look<br>
pretty silly - something like '...stuff >> return ()) >> return ())'.<br>
<br>
So I see the repeated pattern, and by the rule of 3, factor it out to:<br>
<br>
- -- | Convenience function. 'forkIO' and 'forM_' demand return types of<br>
'IO ()', but most interesting<br>
- -- IO functions don't return void. So one adds a call to 'return ()';<br>
this just factors it out.<br>
ignore ∷ (Monad m) ⇒ m a → m ()<br>
ignore x = x >> return ()<br>
<br>
Not the most complex convenience function I've ever written, but not<br>
any simpler than, say Control.Monad.forever or for that matter, most<br>
of the stuff in Control.Monad.<br>
<br>
I'd think it'd be useful for more than just me. Agda is lousy with<br>
calls to '>> return ()'; and then there's ZMachine, arrayref, whim,<br>
the barracuda packages, binary, bnfc, buddha, bytestring, c2hs, cabal,<br>
chesslibrary, comas, conjure, curl, darcs, darcs-benchmark,<br>
dbus-haskell, ddc, dephd, derive, dhs, drift, easyvision, ehc,<br>
filestore, folkung, geni, geordi, gtk2hs, gnuplot, ginsu, halfs,<br>
happstack, haskeline, hback, hbeat... You get the picture.<br>
<br>
I realize the specific name of 'ignore' can be bikeshedded to death,<br>
but it's clear, it's short, Hoogle turns up one other function with<br>
ignore in its name (Distribution.ParseUtils ignoreUnrec), and it's<br>
been independently named 'ignore' by another Haskeller (lilac).<br>
<br>
Existing uses of the string 'ignore are rare - it's in a few places as<br>
a variable, cabal and cabal-install and ehc and tar have where<br>
definitions of an ignore, a test for directory defines an ignore and<br>
imports Control.Monad unqualified, fit defines an 'ignore' but doesn't<br>
seem to use it in any module that also imports Control.Monad<br>
unqualified, halipeto defines an ignore but doesn't import<br>
Control.Monad, shim/yi has a let definition of an ignore, yhc has a<br>
where definition of an ignore. And that's about it. One of directory's<br>
tests would break, and the rest might have an additional -Wall<br>
warning.<br>
<br>
- --<br>
gwern<br>
-----BEGIN PGP SIGNATURE-----<br>
Version: GnuPG v1.4.9 (GNU/Linux)<br>
<br>
iEYEAREKAAYFAkov5Q0ACgkQvpDo5Pfl1oIsRQCghUqynThzcT+OYV1KaYJhGFhv<br>
6yYAnjf7CVOm0+Fg1FBa9IpdVIrRpCZm<br>
=Cd8V<br>
-----END PGP SIGNATURE-----<br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/libraries" target="_blank">http://www.haskell.org/mailman/listinfo/libraries</a><br>
</blockquote></div><br></div>