This time, let's start with the type for Haskell's version of foldl. fn : ('a * 'b -> 'a) -> 'a -> 'b list -> 'a Let us once again derive two functions from this single type signature. Start with the simplest function that has this signature, the function that only uses the first item in a non-empty list. Call this simple function fold. fun fold h x [] = x | fold h x (y::_) = h (x, y); (* does not traverse the input list *) The main body of the function is a single application of h to the pair of x and y. We want to generalize this in two ways in order to get a foldl and a foldr. Look at h (x, y) and look for a way in which it has "two sides" that can be generalized upon. Notice that h has a type 'a parameter and it has a type 'a return value. These are the "two sides" of h (x, y) that will lead us to a foldl and a foldr. First, let's replace the x, the type 'a parameter in h (x, y) with a recursive call to fold (since fold has a type 'a return value) giving fold the x along with the rest of the list. fun fold h x [] = x | fold h x (y::ys) = h (fold h x ys, y); (* a new foldr ? *) Second, let us use the type 'a return value of h (x, y) in a recursive call to fold in the place of fold's type 'a parameter. fun fold h x [] = x | fold h x (y::ys) = fold h (h (x, y)) ys; (* Haskell's foldl *) fun fold h x [] = x | fold h x (y::ys) = h (y, fold h x ys); (* ML's foldr *) fun fold h x [] = x | fold h x (y::ys) = fold h (h (y, x)) ys; (* ML's foldl *) fun folda h x [] = x | folda h x (y::ys) = h (y, folda h x ys); (* ML & Haskell foldr *) fun foldb h x [] = x | foldb h x (y::ys) = foldb h (h (y, x)) ys; (* ML foldl *) fun foldc h x [] = x | foldc h x (y::ys) = h (foldc h x ys, y); (* a new foldr ? *) fun foldd h x [] = x | foldd h x (y::ys) = foldd h (h (x, y)) ys; (* Haskell foldl *)