Consider the following code I wrote:
import Control.Monad
increasing :: Integer -> [Integer]
increasing n
| n == 1 = [1..9]
| otherwise = do let ps = increasing (n - 1)
let last = liftM2 mod ps [10]
let next = liftM2 (*) ps [10]
alternateEndings next last
where alternateEndings xs ys = concat $ zipWith alts xs ys
alts x y = liftM2 (+) [x] [y..9]
Where ‘increasing n‘ should return a list of n-digit numbers whose numbers increase (or stay the same) from left-to-right.
Is there a way to simplify this? The use of ‘let‘ and ‘liftM2‘ everywhere looks ugly to me. I think I’m missing something vital about the list monad, but I can’t seem to get rid of them.
I think what you are trying to do is this:
Or, using a “list comprehension”, which is just special monad syntax for lists:
The idea in the list monad is that you use “bind” (
<-) to iterate over a list of values, andletto compute a single value based on what you have so far in the current iteration. When you use bind a second time, the iterations are nested from that point on.