I’m on the 5th problem of 99 haskell problems. The first attempt went something like this
rev :: [a] -> [a] rev (x:xs) = rev xs ++ x rev [] = []
Let’s analyze this one. Assume we call the function as
rev [1,2,3]
rev (x:xs) matches 1: [2,3], so we have rev [2,3] ++ 1. Similarly, we’ll have rev[3] ++ 2 ++ 1 and then finally rev [] ++ 3 ++ 2 ++ 1. The whole thing can be shown as
step 1: rev [1,2,3] step 2: rev [2,3] ++ 1 step 3: rev [3] ++ 2 ++ 1 step 4: rev [] ++ 3 ++ 2 ++ 1
This gives
[] ++ 3 ++ 2 ++ 1
which is
[3, 2, 1]
Okay, moving forward. Next attempt at writing the function involves usage of foldl. So, here we go
rev xs = foldl (\acc x -> x : acc) [] xs
The foldl function takes the accumulator and an element from the list. The element is prepended onto the accumulator. Which goes like
rev [1,2,3] step 1: acc = [], 1 : acc step 2: acc = [1], 2 : acc step 3: acc = [2,1] , 3 : acc step 4: acc = [3,2,1]
and thus, we get [3,2,1] as result from this.
Now, notice the lambda function. The parameters on left and right are flipped, so why not use the flip function and take advantage of currying?
rev xs = foldl (flip (:)) [] xs
And finally, using point free notation, we can write
rev = foldl (flip (:)) []
Pretty nifty, eh.