The easiest way to understand foldr is to rewrite the list you're folding over without the sugar.
[1,2,3,4,5] => 1:(2:(3:(4:(5:[]))))
now what foldr f x does is that it replaces each : with f in infix form and [] with x and evaluates the result.
For example:
sum [1,2,3] = foldr (+) 0 [1,2,3]
[1,2,3] === 1:(2:(3:[]))
so
sum [1,2,3] === 1+(2+(3+0)) = 6
An easy way to understand foldr is this: It replaces every list constructor with an application of the function provided. Your first example would translate to:
10 - (11 - 54)
from:
10 : (11 : [])
A good piece of advice that I got from the Haskell Wikibook might be of some use here:
As a rule you should use
foldron lists that might be infinite or where the fold is building up a data structure, andfoldl'if the list is known to be finite and comes down to a single value.foldl(without the tick) should rarely be used at all.
Ok, lets look at the arguments:
return value:
It first applies the function to the last element in the list and the empty list result. It then reapplies the function with this result and the previous element, and so forth until it takes some current result and the first element of the list to return the final result.
Fold "folds" a list around an initial result using a function that takes an element and some previous folding result. It repeats this for each element. So, foldr does this starting at the end off the list, or the right side of it.
folr f emptyresult [1,2,3,4] turns into
f(1, f(2, f(3, f(4, emptyresult) ) ) ) . Now just follow parenthesis in evaluation and that's it.
One important thing to notice is that the supplied function f must handle its own return value as its second argument which implies both must have the same type.
Source: my post where I look at it from an imperative uncurried javascript perspective if you think it might help.