Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Here's how I'd write your code:</p> <pre><code>increasing :: Integer -&gt; [Integer] increasing 1 = [1..9] increasing n = let allEndings x = map (10*x +) [x `mod` 10 .. 9] in concatMap allEndings $ increasing (n - 1) </code></pre> <p>I arrived at this code as follows. The first thing I did was to use pattern matching instead of guards, since it's clearer here. The next thing I did was to eliminate the <code>liftM2</code>s. They're unnecessary here, because they're always called with one size-one list; in that case, it's the same as calling <code>map</code>. So <code>liftM2 (*) ps [10]</code> is just <code>map (* 10) ps</code>, and similarly for the other call sites. If you want a general replacement for <code>liftM2</code>, though, you can use <code>Control.Applicative</code>'s <code>&lt;$&gt;</code> (which is just <code>fmap</code>) and <code>&lt;*&gt;</code> to replace <code>liftMn</code> for any <code>n</code>: <code>liftMn f a b c ... z</code> becomes <code>f &lt;$&gt; a &lt;*&gt; b &lt;*&gt; c &lt;*&gt; ... &lt;*&gt; z</code>. Whether or not it's nicer is a matter of taste; I happen to like it.<sup>1</sup> But here, we can eliminate that entirely.</p> <p>The next place I simplified the original code is the <code>do ...</code>. You never actually take advantage of the fact that you're in a <code>do</code>-block, and so that code can become</p> <pre><code>let ps = increasing (n - 1) last = map (`mod` 10) ps next = map (* 10) ps in alternateEndings next last </code></pre> <p>From here, arriving at my code essentially involved writing fusing all of your <code>map</code>s together. One of the only remaining calls that wasn't a <code>map</code> was <code>zipWith</code>. But because you effectively have <code>zipWith alts next last</code>, you only work with <code>10*p</code> and <code>p `mod` 10</code> at the same time, so we can calculate them in the same function. This leads to</p> <pre><code>let ps = increasing (n - 1) in concat $ map alts ps where alts p = map (10*p +) [y `mod` 10..9] </code></pre> <p>And this is basically my code: <code>concat $ map ...</code> should always become <code>concatMap</code> (which, incidentally, is <code>=&lt;&lt;</code> in the list monad), we only use <code>ps</code> once so we can fold it in, and I prefer <code>let</code> to <code>where</code>.</p> <hr> <p><strong>1:</strong> Technically, this only works for <code>Applicative</code>s, so if you happen to be using a monad which hasn't been made one, <code>&lt;$&gt;</code> is <code>`liftM`</code> and <code>&lt;*&gt;</code> is <code>`ap`</code>. All monads can be made applicative functors, though, and many of them have been.</p>
 

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