I've just started to study haskell and i saw this function as a sample solution to a question in this question you should write a function using foldl to reverse a given list.
rev :: [Int]-> [Int]
rev = foldl (\acc x -> x: acc) []
i know what this function is doing and i know that it takes an anonymous function as Argument. what i would like to know is a simple definition of acc (accumulator)in haskell and yes i googled that before! but i still can not understand the it's definition in different functions. is there any rule for using it as an Argument in functions? does it come only in anonymous functions? couldn't we just write it like this \x -> x: xs ?
CodePudding user response:
acc
is just a variable name, it is here the first parameter in the lambda expression indeed:
rev :: [Int] -> [Int]
rev = foldl (\acc x -> x: acc) []
-- ^ first parameter
but you could for example use xs
with:
rev :: [Int] -> [Int]
rev = foldl (\xs x -> x: xs) []
The variable was named acc
because the first parameter of the fold function in foldl :: Foldable f => (b -> a -> b) -> b -> f a -> b
is the "accumulator". But you do not need to name it acc
, nor do we have to work with a lambda expression as folding function. \acc x -> x : acc
can be replaced with flip (:)
, so you can rewrite rev
to:
rev :: [a] -> [a]
rev = foldl (flip (:)) []
CodePudding user response:
'acc' has no definition beyond its type, as described by the type signature of foldl (specialised to lists):
foldl :: (b -> a -> b) -> b -> [a] -> b
the (b -> a -> b)
describes the anonymous function in question
note how the first argument, which is commonly called 'acc' by convention (but could just as easily be called anything else), shares a type with the result of the function - this is due to how the function is used
for example:
foldl (\acc x -> x : acc) [] [1,2,3,4]
= foldl (\acc x -> x : acc) (1 : []) [2,3,4]
= foldl (\acc x -> x : acc) (2 : (1 : [])) [3,4]
= foldl (\acc x -> x : acc) (3 : (2 : (1 : []))) [4]
= foldl (\acc x -> x : acc) (4 : (3 : (2 : (1 : [])))) []
= 4 : (3 : (2 : (1 : [])))
= [4,3,2,1]
as you can see, each step uses the result of the previous step as the first argument - this result is called an "accumulator" for historical reasons, and so calling the argument "acc" suggests what it refers to
this is primarily useful since foldl and foldr swap around the input arguments, so it can be easy to mix up which argument is which when defining folds
naming the accumulator argument 'acc' means you only need to remember which one is which when naming the arguments at the start, and so makes it significantly easier to define more complicated folds, and also makes code more legible in general