Note that there are some explanatory texts on larger screens.

plurals
  1. POComposing monad actions with folds
    text
    copied!<p>Let's take a function of type <code>(Monad m) =&gt; a -&gt; m a</code>. For example:</p> <pre><code>ghci&gt; let f x = Just (x+1) </code></pre> <p>I'd like to be able to apply it any number of times. The first thing I tried was</p> <pre><code>ghci&gt; let times n f = foldr (&gt;=&gt;) return $ replicate n f </code></pre> <p>The problem is that it won't work for large <code>n</code>:</p> <pre><code>ghci&gt; 3 `times` f $ 1 Just 4 ghci&gt; 1000000 `times` f $ 1 Just *** Exception: stack overflow </code></pre> <p>It doesn't work also the other way:</p> <pre><code>ghci&gt; let timesl n f = foldl' (&lt;=&lt;) return $ replicate n f ghci&gt; 3 `timesl` f $ 1 Just 4 ghci&gt; 1000000 `timesl` f $ 1 Just *** Exception: stack overflow </code></pre> <p>Actually, what works is using <code>($!)</code> strictness operator</p> <pre><code>ghci&gt; let timesStrict n f = foldr1 ((&gt;=&gt;) . ($!)) $ replicate n f ghci&gt; 3 `timesStrict` f $ 1 Just 4 ghci&gt; 10000000 `timesStrict` f $ 1 Just 10000001 </code></pre> <p>Is there a nicer or more idiomatic solution? Or probably a stricter one? I still easily get stack overflows if <code>f</code> is a heavy-weight function.</p> <p><em>UPD:</em> I found that writing <code>times</code> in a pointful form does not solve the problem of composing heavy-weight monadic actions neither. This works for f x = Just (x+1) but fails in the real world:</p> <pre><code>times f 0 a = return a times f i a = (f $! a) &gt;&gt;= times f (i - 1) </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload