Non-trivial algorithm conversion from imperative to functional - list

To enforce my (weak) functional programming skills, I am studying The NURBS book by Piegl and Tiller converting all the algorithms to Haskell. It is a very nice and instructive process but I got stuck on algorithm 2.2, here is (a C-like reworked-by-me version of) the pseudo-code:
double[] BasisFuns( int i, double u, int p, double U[]) {
double N[p+1];
double left[p+1];
double ritght[p+1];
N[0]=1.0;
for (j=1; j<=p; j++) {
left[j] = u - U[i+1-j];
right[j] = U[i+j] - u;
double saved = 0.0;
for (r=O; r<j; r++) {
double temp= N[r]/(right[r+1]+left[j-r]);
N[r] = saved+right[r+1]*temp;
saved = left[j-r]*temp;
}
N[j] = saved;
}
return N;
}
The outer loop looks easy, but the inner one, with all those necessarily-ordered modifications to the elements of N is giving me a headache.
I started to set it up like this:
baseFunc :: RealFrac a => Int -> Int -> a -> [a] -> [a]
baseFunc i p u knots
[ ??? | j <- [1..p], r <- [0..j] ]
where
left = [ u - knots !! (i+1-j) | j <- [ 1 .. p ]
right= [ knots !! (i+j) - u | j <- [ 1 .. p ]
but I feel that I may be completely off road.
I have already written a completely different and inefficient version of this function based on Eq. 2.5 in the book, therefore here I am looking to maintain the performance of the imperative version.

Although it is certainly possible to translate numerical algorithms into Haskell starting from Fortran/Matlab/C “everything is an array” style (and, using unboxed mutable vectors, performance will generally be not much worse) this is really missing the point about using a functional language. The underlying math is actually much closer to functional than to imperative programming, so the best thing is to start right there. Specifically, the recurrence formula
can be translated almost literally into Haskell, much better than into an imperative language:
baseFuncs :: [Double] -- ^ Knots, \(\{u_i\}_i\)
-> Int -- ^ Index \(i\) at which to evaluate
-> Int -- ^ Spline degree \(p\)
-> Double -- ^ Position \(u\) at which to evaluate
-> Double
baseFuncs us i 0 u
| u >= us!!i, u < us!!(i+1) = 1
| otherwise = 0
baseFuncs us i p u
= (u - us!!i)/(us!!(i+p) - us!!i) * baseFuncs us i (p-1) u
+ (us!!(i+p+1) - u)/(us!!(i+p+1) - us!!(i+1)) * baseFuncs us (i+1) (p-1) u
Unfortunately this will actually not be efficient though, for multiple reasons.
First, lists suck at random-access. A simple fix is to switch to unboxed (but pure) vectors. While we're at is let's wrap them in a newtype because the ui are supposed to be strictly increasing. Talking about types: the direct accesses are unsafe; we could fix this by bringing p and the number of segments to the type level and only allowing indices i < n-p, but I won't go into that here.
Also, it's awkward to pass us and u around all the way down the recursion, better just bind it once and then use a helper function to go down:
import Data.Vector.Unboxed (Vector, (!))
import qualified Data.Vector.Unboxed as VU
newtype Knots = Knots {getIncreasingKnotsSeq :: Vector Double}
baseFuncs :: Knots -- ^ \(\{u_i\}_i\)
-> Int -- ^ Index \(i\) at which to evaluate
-> Int -- ^ Spline degree \(p\)
-> Double -- ^ Position \(u\) at which to evaluate
-> Double
baseFuncs (Knots us) i₀ p₀ u = go i₀ p₀
where go i 0
| u >= us!i
, i>=VU.length us-1 || u < us!(i+1) = 1
| otherwise = 0
go i p
= (u - us!i)/(us!(i+p) - us!i) * go i (p-1)
+ (us!(i+p+1) - u)/(us!(i+p+1) - us!(i+1)) * go (i+1) (p-1)
The other thing that's not optimal is that we don't share the lower-level evaluations between neighbouring recursive calls. (The evaluation is effectively spanning a directed graph with p2⁄2 nodes, but we evaluate it as a tree with 2p nodes.) That's a massive inefficiency for large p, but actually quite harmless for the typical low-degree splines.
The way to avoid this inefficiency is to memoise. The C version does this explicitly with the N array, but – this being Haskell – we can be lazy to save the effort of allocating the correct size by using a generic memoisation library, e.g. memo-trie:
import Data.MemoTrie (memo2)
baseFuncs (Knots us) i₀ p₀ u = go' i₀ p₀
where go i 0
| u >= us!i
, i>=VU.length us || u < us!(i+1) = 1
| otherwise = 0
go i p
= (u - us!i)/(us!(i+p) - us!i) * go' i (p-1)
+ (us!(i+p+1) - u)/(us!(i+p+1) - us!(i+1)) * go' (i+1) (p-1)
go' = memo2 go
That was the no-brains version (“just memoise the entire domain of go”). As dfeuer remarks, it is easy enough to explicitly memoise only the regian that actually gets evaluated, and then we can again use an efficient unboxed vector:
baseFuncs (Knots us) i₀ p₀ u = VU.unsafeHead $ gol i₀ p₀
where gol i 0 = VU.generate (p₀+1) $ \j ->
if u >= us!(i+j)
&& (i+j>=VU.length us || u < us!(i+j+1))
then 1 else 0
gol i p = case gol i (p-1) of
res' -> VU.izipWith
(\j l r -> let i' = i+j
in (u - us!i')/(us!(i'+p) - us!i') * l
+ (us!(i'+p+1) - u)/(us!(i'+p+1) - us!(i'+1)) * r)
res' (VU.unsafeTail res')
(I can safely use unsafeHead and unsafeTail here, because at each recursion level the zipping reduces the length by 1, so at the top-level I still have p₀ - (p₀-1) = 1 elements left.)
This version should, I think, have the same asymptotics as the C version. With some more small improvements like precomputing the interval lengths and pre-checking that the arguments are in the allowed range so all accesses can be made unsafe, it is probably very close in performance to the C version.
As – again – dfeuer remarks, it might not even be necessary to use vectors there because I just zip together the result. For this kind of stuff, GHC can be very good at optimising code even when using plain lists. But, I won't investigate the performance any further here.
The test I used to confirm it actually works:
https://gist.github.com/leftaroundabout/4fd6ef8642029607e1b222783b9d1c1e

(Disclaimer: I have zero idea of what is being calculated here.)
The access pattern in the array U seems to be as follows: from the index i outwards, we consume values to the left and to the right. We could imagine having two lists which consisted precisely in those sequences of elements. In fact, we could construct such lists out of a source list like this:
pryAt :: Int -> [a] -> ([a], [a])
pryAt i xs = go i ([], xs)
where
go 0 a = a
go n (us, v : vs) = go (pred n) (v : us, vs)
-- pryAt 5 ['a'..'x']
-- ("edcba","fghijklmnopqrstuvwx")
For random-access containers, we could have specialized versions of pryAt, because traversing the whole list until we reach the ith element will be inefficient.
In the outer loop, we have arrays N, left and right which grow with each iteration (N seems to be fully reconstructed at each iteration, as well). We could represent them as lists. In each iteration, we also consume a pair of elements of U, to the left and right.
The following datatype represents the situation at the beginning of an iteration of the outer loop:
data State = State
{ ns :: [Double],
left :: [Double],
right :: [Double],
us :: ([Double], [Double])
}
Assuming we already had the outerStep :: State -> State implemented, we could simply turn the crank p times:
basis :: Int -> Double -> Int -> [Double] -> [Double]
basis i u p us =
ns $ iterate outerStep initial !! p
where
initial =
State
{ ns = [1.0],
left = [],
right = [],
us = pryAt i us
}
What is done at outerStep? We add new elements to left and right, then we re-create the whole N list from the beginning, while carrying a saved accumulator along the way. This is a mapAccumR. We need some extra info: the right values (in the same direction as N) and the left values (in reverse direction) so we need to zip them beforehand:
outerStep (State {ns, left, right, us = (ul : uls, ur : urs)}) =
let left' = u - ul : left
right' = ur - u : right
(saved', ns') = mapAccumR innerStep 0.0 $ zip3 ns right' (reverse left')
in State
{ ns = saved' : ns',
left = left',
right = right',
us = (uls, urs)
}
And here are the computations of the inner step:
innerStep saved (n, r, l) =
let temp = n / (r - l)
n' = saved + r
saved' = l * temp
in (saved', n')
In addition to correcting possible bugs, more work would remain because the basis function in its current form is likely to leak memory (in particular, that mapAccumR will create lots of thunks). Perhaps it could be rewritten to use functions like iterate' or foldl' that keep their accumulators strict.

I'm not sure that it will work, but...:
baseFunc :: RealFrac a => Int -> Int -> a -> [a] -> [a]
baseFunc i p u knots =
foldl' helper [1.0] [1..p]
where
left = [ u - knots !! (i+1-j) | j <- [ 1 .. p ] ]
right= [ knots !! (i+j) - u | j <- [ 1 .. p ] ]
helper N j = outer_loop j N left right
inner_loop :: RealFrac a => Int -> Int -> [a] -> [a] -> [a] -> a -> (a, a)
inner_loop r j N left right saved =
let temp = N !! r / (right !! (r+1) + left !! (j-r))
in (saved + right !! (r+1) * temp, left !! (j-r) * temp)
outer_loop :: RealFrac a => Int -> [a] -> [a] -> [a] -> [a]
outer_loop j N left right =
let (new_N, saved) = foldl' helper (N, 0.0) [0..j-1]
helper (prev_N, saved) r =
let (N_r, new_saved) = inner_loop r j prev_N left right saved
in (insertAt r N_r prev_N, new_saved)
in new_N ++ [saved]

Related

Haskell - Calculate complex sum using lists

for a given list by user s=[x1,x2,...,xk] I need to calculate the sum of
x1 * (x2+x3+...x4)
+ (x1+x2) * (x3+x4+...xk)
+ ...
+ (x1+x2+...+x(k-2)) * (x(k-1) + xk)
+ (x1+x2+...+x(k-1)) * xk
from a function [Int]->Int
Please see the math formula in the following photo for better understanding :
https://imgur.com/gallery/Oqgpkcu
just tried very little things like calculating the sum of the list minus the last element. By the way i must implement all of this by using lists and very basic functions (head, tail ,init )
xsum :: [Int] -> Int
xsum s = sumIntList (init s)
sumIntList :: [Int] -> Int
sumIntList (h:t) = h + sumIntList t
sumIntList [] = 0
some of the result that SHOULD be produced by the calling of the function are :
xsum [4,5,8]
124
xsum [1..100]
341665830
Thanks for reading !
The image you provided says * rather than ^. It would be good to see some of your attempts. One simple approach would be to map the function splitAt across each possible index, then use the function sum on each pair to get the (initial segment sum, final segment sum) pair, then for each pair multiply its elements together, then sum all the resulting products. How far can you get with coding that up?
EDIT: to save potential future readers from scrolling through all the comments, a potential implementation is given below that uses only sum. It is suboptimal because it sums the same sublists many times over, a better implementation might start by using scanl in both directions to generate the partial sums and proceed from there.
xsum (x:xs#(y:ys)) = x * sum xs + xsum ((x+y):ys)
xsum _ = 0
EDIT2: We have a (sort of) forwards-travelling and backwards-travelling thing going on, I like it!
xsum = fst . xsum'
where xsum' (x:xs#(y:ys)) = (\(acc,s) -> (acc + x * (s-x),s) ) $ xsum' ((x+y):ys)
xsum' [] = (0,0)
xsum' [x] = (0,x)

Haskell - Defining result as a list and returning null

listX n = xs
if sum[x | x <- [2, 4..n-1], y <- [1..n-1], y `rem` x == 0] == y
then insert y xs
else return ()
Alright, first time trying to work with Haskell, and only having novice Java knowledge has led to some problems.
What I was trying to do, was to define the result of the function listX n as a list called xs.
My idea was that the program would grab every number of from 1 to n, and check if it was equal to the sum of its positive divisors.
Clearly, I have failed horribly and need help, pointers to concepts I haven't understood is extremely appreciated.
Your main problem seems to be that you still think imperative (with the insert) - also () is the value unit - you probably wanted to write [] (the empty list) instead - but still the xs here is totally undefined so you would have to fix this too (and I don't see how to be honest).
perfect numbers
I think I can see a basic idea in there, and I think the best way to fix this is to go full list-comprehension (as you seem to understand them quite well) - here is a version that should work:
listX n = [ x | x <- [1..n], sum [ y | y <- [1..x-1], x `mod` y == 0] == x]
As you can see I changed this a bit - first I check all x from 1 to n if they could be perfect - and I do this by checking by summing up all proper divisors and checking if the sum is equal to x (that's the job of the sum [...] == x part) - in case you don't know this works because you can add guards to list comprehensions (the sum [..] == x filters out all values of x where this is true).
a nicer version
to make this a bit more readable (and separate the concerns) I would suggest writing it that way:
properDivisors :: Integer -> [Integer]
properDivisors n = [ d | d <- [1..n-1], n `mod` d == 0]
isPerfect :: Integer -> Bool
isPerfect n = sum (properDivisors n) == n
perfectNumbers :: [Integer]
perfectNumbers = filter isPerfect [1..]
perfectNumbersUpTo :: Integer -> [Integer]
perfectNumbersUpTo n = takeWhile (<= n) perfectNumbers

How can I fold with state in Haskell?

I have a simple function (used for some problems of project Euler, in fact). It turns a list of digits into a decimal number.
fromDigits :: [Int] -> Integer
fromDigits [x] = toInteger x
fromDigits (x:xs) = (toInteger x) * 10 ^ length xs + fromDigits xs
I realized that the type [Int] is not ideal. fromDigits should be able to take other inputs like e.g. sequences, maybe even foldables ...
My first idea was to replace the above code with sort of a "fold with state". What is the correct (= minimal) Haskell-category for the above function?
First, folding is already about carrying some state around. Foldable is precisely what you're looking for, there is no need for State or other monads.
Second, it'd be more natural to have the base case defined on empty lists and then the case for non-empty lists. The way it is now, the function is undefined on empty lists (while it'd be perfectly valid). And notice that [x] is just a shorthand for x : [].
In the current form the function would be almost expressible using foldr. However within foldl the list or its parts aren't available, so you can't compute length xs. (Computing length xs at every step also makes the whole function unnecessarily O(n^2).) But this can be easily avoided, if you re-thing the procedure to consume the list the other way around. The new structure of the function could look like this:
fromDigits' :: [Int] -> Integer
fromDigits' = f 0
where
f s [] = s
f s (x:xs) = f (s + ...) xs
After that, try using foldl to express f and finally replace it with Foldable.foldl.
You should avoid the use of length and write your function using foldl (or foldl'):
fromDigits :: [Int] -> Integer
fromDigits ds = foldl (\s d -> s*10 + (fromIntegral d)) 0 ds
From this a generalization to any Foldable should be clear.
A better way to solve this is to build up a list of your powers of 10. This is quite simple using iterate:
powersOf :: Num a => a -> [a]
powersOf n = iterate (*n) 1
Then you just need to multiply these powers of 10 by their respective values in the list of digits. This is easily accomplished with zipWith (*), but you have to make sure it's in the right order first. This basically just means that you should re-order your digits so that they're in descending order of magnitude instead of ascending:
zipWith (*) (powersOf 10) $ reverse xs
But we want it to return an Integer, not Int, so let's through a map fromIntegral in there
zipWith (*) (powersOf 10) $ map fromIntegral $ reverse xs
And all that's left is to sum them up
fromDigits :: [Int] -> Integer
fromDigits xs = sum $ zipWith (*) (powersOf 10) $ map fromIntegral $ reverse xs
Or for the point-free fans
fromDigits = sum . zipWith (*) (powersOf 10) . map fromIntegral . reverse
Now, you can also use a fold, which is basically just a pure for loop where the function is your loop body, the initial value is, well, the initial state, and the list you provide it is the values you're looping over. In this case, your state is a sum and what power you're on. We could make our own data type to represent this, or we could just use a tuple with the first element being the current total and the second element being the current power:
fromDigits xs = fst $ foldr go (0, 1) xs
where
go digit (s, power) = (s + digit * power, power * 10)
This is roughly equivalent to the Python code
def fromDigits(digits):
def go(digit, acc):
s, power = acc
return (s + digit * power, power * 10)
state = (0, 1)
for digit in digits:
state = go(digit, state)
return state[0]
Such a simple function can carry all its state in its bare arguments. Carry around an accumulator argument, and the operation becomes trivial.
fromDigits :: [Int] -> Integer
fromDigits xs = fromDigitsA xs 0 # 0 is the current accumulator value
fromDigitsA [] acc = acc
fromDigitsA (x:xs) acc = fromDigitsA xs (acc * 10 + toInteger x)
If you're really determined to use a right fold for this, you can combine calculating length xs with the calculation like this (taking the liberty of defining fromDigits [] = 0):
fromDigits xn = let (x, _) = fromDigits' xn in x where
fromDigits' [] = (0, 0)
fromDigits' (x:xn) = (toInteger x * 10 ^ l + y, l + 1) where
(y, l) = fromDigits' xn
Now it should be obvious that this is equivalent to
fromDigits xn = fst $ foldr (\ x (y, l) -> (toInteger x * 10^l + y, l + 1)) (0, 0) xn
The pattern of adding an extra component or result to your accumulator, and discarding it once the fold returns, is a very general one when you're re-writing recursive functions using folds.
Having said that, a foldr with a function that is always strict in its second parameter is a really, really bad idea (excessive stack usage, maybe a stack overflow on long lists) and you really should write fromDigits as a foldl as some of the other answers have suggested.
If you want to "fold with state", probably Traversable is the abstraction you're looking for. One of the methods defined in Traversable class is
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
Basically, traverse takes a "stateful function" of type a -> f b and applies it to every function in the container t a, resulting in a container f (t b). Here, f can be State, and you can use traverse with function of type Int -> State Integer (). It would build an useless data structure (list of units in your case), but you can just discard it. Here's a solution to your problem using Traversable:
import Control.Monad.State
import Data.Traversable
sumDigits :: Traversable t => t Int -> Integer
sumDigits cont = snd $ runState (traverse action cont) 0
where action x = modify ((+ (fromIntegral x)) . (* 10))
test1 = sumDigits [1, 4, 5, 6]
However, if you really don't like building discarded data structure, you can just use Foldable with somewhat tricky Monoid implementation: store not only computed result, but also 10^n, where n is count of digits converted to this value. This additional information gives you an ability to combine two values:
import Data.Foldable
import Data.Monoid
data Digits = Digits
{ value :: Integer
, power :: Integer
}
instance Monoid Digits where
mempty = Digits 0 1
(Digits d1 p1) `mappend` (Digits d2 p2) =
Digits (d1 * p2 + d2) (p1 * p2)
sumDigitsF :: Foldable f => f Int -> Integer
sumDigitsF cont = value $ foldMap (\x -> Digits (fromIntegral x) 10) cont
test2 = sumDigitsF [0, 4, 5, 0, 3]
I'd stick with first implementation. Although it builds unnecessary data structure, it's shorter and simpler to understand (as far as a reader understands Traversable).

Better way of taking random sample without replacement from list in Haskell

I need to take a random sample without replacement (each element only occurring once in the sample) from a longer list. I'm using the code below, but now I'd like to know:
Is there a library function that does this?
How can I improve this code? (I'm a Haskell beginner, so this would be useful even if there is a library function).
The purpose of the sampling is to be able to generalize findings from analyzing the sample to the population.
import System.Random
-- | Take a random sample without replacement of size size from a list.
takeRandomSample :: Int -> Int -> [a] -> [a]
takeRandomSample seed size xs
| size < hi = subset xs rs
| otherwise = error "Sample size must be smaller than population."
where
rs = randomSample seed size lo hi
lo = 0
hi = length xs - 1
getOneRandomV g lo hi = randomR (lo, hi) g
rsHelper size lo hi g x acc
| x `notElem` acc && length acc < size = rsHelper size lo hi new_g new_x (x:acc)
| x `elem` acc && length acc < size = rsHelper size lo hi new_g new_x acc
| otherwise = acc
where (new_x, new_g) = getOneRandomV g lo hi
-- | Get a random sample without replacement of size size between lo and hi.
randomSample seed size lo hi = rsHelper size lo hi g x [] where
(x, g) = getOneRandomV (mkStdGen seed) lo hi
subset l = map (l !!)
Here's a quick 'back-of-the-envelope' implementation of what Daniel Fischer suggested in his comment, using my preferred PRNG (mwc-random):
{-# LANGUAGE BangPatterns #-}
module Sample (sample) where
import Control.Monad.Primitive
import Data.Foldable (toList)
import qualified Data.Sequence as Seq
import System.Random.MWC
sample :: PrimMonad m => [a] -> Int -> Gen (PrimState m) -> m [a]
sample ys size = go 0 (l - 1) (Seq.fromList ys) where
l = length ys
go !n !i xs g | n >= size = return $! (toList . Seq.drop (l - size)) xs
| otherwise = do
j <- uniformR (0, i) g
let toI = xs `Seq.index` j
toJ = xs `Seq.index` i
next = (Seq.update i toI . Seq.update j toJ) xs
go (n + 1) (i - 1) next g
{-# INLINE sample #-}
This is pretty much a (terse) functional rewrite of R's internal C version of sample() as it's called without replacement.
sample is just a wrapper over a recursive worker function that incrementally shuffles the population until the desired sample size is reached, returning only that many shuffled elements. Writing the function like this ensures that GHC can inline it.
It's easy to use:
*Main> create >>= sample [1..100] 10
[51,94,58,3,91,70,19,65,24,53]
A production version might want to use something like a mutable vector instead of Data.Sequence in order to cut down on time spent doing GC.
I think a standard way to do this is to keep a fixed-size buffer initialized with the first N elements, and for each i'th element, i >= N, do this:
Pick a random number, j, between 0 and i.
If j < N then replace the j'th element in the buffer with the current one.
You can prove correctness by induction:
This clearly generates a random sample (I assume order is irrelevant) if you only have N elements. Now suppose it's true up to the i'th element. This means that the probability of any element being in the buffer is N/(i+1) (I start counting at 0).
After picking the random number, the probability that the i+1'th element is in the buffer is N/(i+2) (j is between 0 and i+1, and N of those end up in the buffer). What about the others?
P(k'th element is in the buffer after processing the i+1'th) =
P(k'th element was in the buffer before)*P(k'th element is not replaced) =
N/(i+1) * (1-1/(i+2)) =
N/(i+2)
Here's some code that does it, in sample-size space, using the standard (slow) System.Random.
import Control.Monad (when)
import Data.Array
import Data.Array.ST
import System.Random (RandomGen, randomR)
sample :: RandomGen g => g -> Int -> [Int] -> [Int]
sample g size xs =
if size < length xs
then error "sample size must be >= input length"
else elems $ runSTArray $ do
arr <- newListArray (0, size-1) pre
loop arr g size post
where
(pre, post) = splitAt size xs
loop arr g i [] = return arr
loop arr g i (x:xt) = do
let (j, g') = randomR (0, i) g
when (j < size) $ writeArray arr j x
loop arr g' (i+1) xt

Haskell: How to simplify or eliminate liftM2?

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.
Well, as far as liftM functions go, my preferred way to use those is the combinators defined in Control.Applicative. Using those, you'd be able to write last = mod <$> ps <*> [10]. The ap function from Control.Monad does the same thing, but I prefer the infix version.
What (<$>) and (<*>) goes like this: liftM2 turns a function a -> b -> c into a function m a -> m b -> m c. Plain liftM is just (a -> b) -> (m a -> m b), which is the same as fmap and also (<$>).
What happens if you do that to a multi-argument function? It turns something like a -> b -> c -> d into m a -> m (b -> c -> d). This is where ap or (<*>) come in: what they do is turn something like m (a -> b) into m a -> m b. So you can keep stringing it along that way for as many arguments as you like.
That said, Travis Brown is correct that, in this case, it seems you don't really need any of the above. In fact, you can simplify your function a great deal: For instance, both last and next can be written as single-argument functions mapped over the same list, ps, and zipWith is the same as a zip and a map. All of these maps can be combined and pushed down into the alts function. This makes alts a single-argument function, eliminating the zip as well. Finally, the concat can be combined with the map as concatMap or, if preferred, (>>=). Here's what it ends up:
increasing' :: Integer -> [Integer]
increasing' 1 = [1..9]
increasing' n = increasing' (n - 1) >>= alts
where alts x = map ((x * 10) +) [mod x 10..9]
Note that all refactoring I did to get to that version from yours was purely syntactic, only applying transformations that should have no impact on the result of the function. Equational reasoning and referential transparency are nice!
I think what you are trying to do is this:
increasing :: Integer -> [Integer]
increasing 1 = [1..9]
increasing n = do p <- increasing (n - 1)
let last = p `mod` 10
next = p * 10
alt <- [last .. 9]
return $ next + alt
Or, using a "list comprehension", which is just special monad syntax for lists:
increasing2 :: Integer -> [Integer]
increasing2 1 = [1..9]
increasing2 n = [next + alt | p <- increasing (n - 1),
let last = p `mod` 10
next = p * 10,
alt <- [last .. 9]
]
The idea in the list monad is that you use "bind" (<-) to iterate over a list of values, and let to 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.
It looks very unusual to me to use liftM2 (or <$> and <*>) when one of the arguments is always a singleton list. Why not just use map? The following does the same thing as your code:
increasing :: Integer -> [Integer]
increasing n
| n == 1 = [1..9]
| otherwise = do let ps = increasing (n - 1)
let last = map (flip mod 10) ps
let next = map (10 *) ps
alternateEndings next last
where alternateEndings xs ys = concat $ zipWith alts xs ys
alts x y = map (x +) [y..9]
Here's how I'd write your code:
increasing :: Integer -> [Integer]
increasing 1 = [1..9]
increasing n = let allEndings x = map (10*x +) [x `mod` 10 .. 9]
in concatMap allEndings $ increasing (n - 1)
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 liftM2s. They're unnecessary here, because they're always called with one size-one list; in that case, it's the same as calling map. So liftM2 (*) ps [10] is just map (* 10) ps, and similarly for the other call sites. If you want a general replacement for liftM2, though, you can use Control.Applicative's <$> (which is just fmap) and <*> to replace liftMn for any n: liftMn f a b c ... z becomes f <$> a <*> b <*> c <*> ... <*> z. Whether or not it's nicer is a matter of taste; I happen to like it.1 But here, we can eliminate that entirely.
The next place I simplified the original code is the do .... You never actually take advantage of the fact that you're in a do-block, and so that code can become
let ps = increasing (n - 1)
last = map (`mod` 10) ps
next = map (* 10) ps
in alternateEndings next last
From here, arriving at my code essentially involved writing fusing all of your maps together. One of the only remaining calls that wasn't a map was zipWith. But because you effectively have zipWith alts next last, you only work with 10*p and p `mod` 10 at the same time, so we can calculate them in the same function. This leads to
let ps = increasing (n - 1)
in concat $ map alts ps
where alts p = map (10*p +) [y `mod` 10..9]
And this is basically my code: concat $ map ... should always become concatMap (which, incidentally, is =<< in the list monad), we only use ps once so we can fold it in, and I prefer let to where.
1: Technically, this only works for Applicatives, so if you happen to be using a monad which hasn't been made one, <$> is `liftM` and <*> is `ap`. All monads can be made applicative functors, though, and many of them have been.
I think it's cleaner to pass last digit in a separate parameter and use lists.
f a 0 = [[]]
f a n = do x <- [a..9]
k <- f x (n-1)
return (x:k)
num = foldl (\x y -> 10*x + y) 0
increasing = map num . f 1