I’m learning Haskell now and I’m facing the following problem:
I want to rewrite the ++ function using foldl’ and foldr. I’ve done it with foldr:
myConcat xs ys = foldr (:) ys xs
I can’t do it using foldl’. I’ve read in RealWorldHaskell that foldr is useful for doing this kind of thing.
Ok, but can’t I also write an equivalant to ++ using foldl? Can someone show me how I can do this (if it can be done… The book doesn’t mention anything about it)…
Does Haskell’s type mechanism prevent me from doing this? Every time I tried I got a type error…
I’m guessing the error which you get is from trying to simply switch
foldrtofoldl':which produces the error (using my Hugs REPL):
Notice in the last two lines (the provided type and the expected type) that the positions of
[a]andaare in the opposite positions. This means we need a function which is sort of like(:), but which takes its arguments in the opposite order.Haskell has a function which does this for us: the
flipfunction. Basically,flipis equivalent toThat is,
fliptakes a binary function as an argument, and returns another binary function whose arguments are reversed (“flipped”) from the original. So while(:)has the typea -> [a] -> [a], we see thatflip (:)has the type[a] -> a -> [a], making it a perfect candidate as a parameter tofoldl'.Using
flip, we now have this code:This result from the fact that
foldl'has the type(a -> b -> c) -> a -> [b] -> cRunning this with arguments
[1..5]and[6..10], we get a result of[5,4,3,2,1,6,7,8,9,10], which is almost what we want. The only problem is that the first list turns out backwards in the result. Adding a simple call toreversegives us our final definition ofmyConcat:Looking over this process shows one of the nice things that often comes up when writing Haskell code: when you run into a problem, you can solve it one (small) step at a time. This is especially true when you already have one working implementation, and you are simply trying to write another. The big thing to notice is that if you change one part of the implementation (in this case, changing
foldrtofoldl'), then many of the other needed changes simply fall out of the type definitions. The few that remain are correctedness problems which can readily be found, either by running test cases, or by looking at the exact nature of the functions used.PS: any Haskell guys who can freshen up that last line of code, feel free to do so. While it’s not horrible, I don’t find it to be very pretty. Unfortunately, I’m not that good with Haskell yet.