Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5956883
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T18:19:17+00:00 2026-05-22T18:19:17+00:00

In Real World Haskell , Chapter 4. on Functional Programming : Write foldl with

  • 0

In Real World Haskell, Chapter 4. on Functional Programming:

Write foldl with foldr:

-- file: ch04/Fold.hs
myFoldl :: (a -> b -> a) -> a -> [b] -> a

myFoldl f z xs = foldr step id xs z
    where step x g a = g (f a x)

The above code confused me a lot, and somebody called dps rewrote it with a meaningful name to make it a bit clearer:

myFoldl stepL zeroL xs = (foldr stepR id xs) zeroL
where stepR lastL accR accInitL = accR (stepL accInitL lastL)

Somebody else, Jef G, then did an excellent job by providing an example and showing the underlying mechanism step by step:

myFoldl (+) 0 [1, 2, 3]
= (foldR step id [1, 2, 3]) 0
= (step 1 (step 2 (step 3 id))) 0
= (step 1 (step 2 (\a3 -> id ((+) a3 3)))) 0
= (step 1 (\a2 -> (\a3 -> id ((+) a3 3)) ((+) a2 2))) 0
= (\a1 -> (\a2 -> (\a3 -> id ((+) a3 3)) ((+) a2 2)) ((+) a1 1)) 0
= (\a1 -> (\a2 -> (\a3 -> (+) a3 3) ((+) a2 2)) ((+) a1 1)) 0
= (\a1 -> (\a2 -> (+) ((+) a2 2) 3) ((+) a1 1)) 0
= (\a1 -> (+) ((+) ((+) a1 1) 2) 3) 0
= (+) ((+) ((+) 0 1) 2) 3
= ((0 + 1) + 2) + 3

But I still cannot fully understand that, here are my questions:

  1. What is the id function for? What is the role of? Why should we need it here?
  2. In the above example, id function is the accumulator in the lambda function?
  3. foldr’s prototype is foldr :: (a -> b -> b) -> b -> [a] -> b, and the first parameter is a function which need two parameters, but the step function in the myFoldl’s implementation uses 3 parameters, I’m complelely confused!
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T18:19:18+00:00Added an answer on May 22, 2026 at 6:19 pm

    Some explanations are in order!

    What is the id function for? What is the role of? Why should we need it here?

    id is the identity function, id x = x, and is used as the equivalent of zero when building up a chain of functions with function composition, (.). You can find it defined in the Prelude.

    In the above example, id function is the accumulator in the lambda function?

    The accumulator is a function that is being built up via repeated function application. There’s no explicit lambda, since we name the accumulator, step. You can write it with a lambda if you want:

    foldl f a bs = foldr (\b g x -> g (f x b)) id bs a
    

    Or as Graham Hutton would write:

    5.1 The foldl operator

    Now let us generalise from the suml example and consider the standard operator foldl that processes the elements of a list in left-to-right order by using a function f to combine values, and a value v as the starting value:

    foldl :: (β → α → β) → β → ([α] → β)
    foldl f v [ ] = v
    foldl f v (x : xs) = foldl f (f v x) xs
    

    Using this operator, suml can be redefined simply by suml = foldl (+) 0. Many other functions can be defined in a simple way using foldl. For example, the standard function reverse can redefined using foldl as follows:

    reverse :: [α] → [α]
    reverse = foldl (λxs x → x : xs) [ ]
    

    This definition is more efficient than our original definition using fold, because it avoids the use of the inefficient append operator (++) for lists.

    A simple generalisation of the calculation in the previous section for the function suml shows how to redefine the function foldl in terms of fold:

    foldl f v xs = fold (λx g → (λa → g (f a x))) id xs v
    

    In contrast, it is not possible to redefine fold in terms of foldl, due to the fact that
    foldl is strict in the tail of its list argument but fold is not. There are a number of useful ‘duality theorems’ concerning fold and foldl, and also some guidelines for deciding which operator is best suited to particular applications (Bird, 1998).

    foldr’s prototype is foldr :: (a -> b -> b) -> b -> [a] -> b

    A Haskell programmer would say that the type of foldr is (a -> b -> b) -> b -> [a] -> b.

    and the first parameter is a function which need two parameters, but the step function in the myFoldl’s implementation uses 3 parameters, I’m complelely confused

    This is confusing and magical! We play a trick and replace the accumulator with a function, which is in turn applied to the initial value to yield a result.

    Graham Hutton explains the trick to turn foldl into foldr in the above article. We start by writing down a recursive definition of foldl:

    foldl :: (a -> b -> a) -> a -> [b] -> a
    foldl f v []       = v
    foldl f v (x : xs) = foldl f (f v x) xs
    

    And then refactor it via the static argument transformation on f:

    foldl :: (a -> b -> a) -> a -> [b] -> a    
    foldl f v xs = g xs v
        where
            g []     v = v
            g (x:xs) v = g xs (f v x)
    

    Let’s now rewrite g so as to float the v inwards:

    foldl f v xs = g xs v
        where
            g []     = \v -> v
            g (x:xs) = \v -> g xs (f v x)
    

    Which is the same as thinking of g as a function of one argument, that returns a function:

    foldl f v xs = g xs v
        where
            g []     = id
            g (x:xs) = \v -> g xs (f v x)
    

    Now we have g, a function that recursively walks a list, apply some function f. The final value is the identity function, and each step results in a function as well.

    But, we have handy already a very similar recursive function on lists, foldr!

    2 The fold operator

    The fold operator has its origins in recursion theory (Kleene, 1952), while the use
    of fold as a central concept in a programming language dates back to the reduction operator of APL (Iverson, 1962), and later to the insertion operator of FP (Backus,
    1978). In Haskell, the fold operator for lists can be defined as follows:

    fold :: (α → β → β) → β → ([α] → β)
    fold f v [ ] = v
    fold f v (x : xs) = f x (fold f v xs)
    

    That is, given a function f of type α → β → β and a value v of type β, the function
    fold f v processes a list of type [α] to give a value of type β by replacing the nil
    constructor [] at the end of the list by the value v, and each cons constructor (:) within the list by the function f. In this manner, the fold operator encapsulates a simple pattern of recursion for processing lists, in which the two constructors for lists are simply replaced by other values and functions. A number of familiar functions on lists have a simple definition using fold.

    This looks like a very similar recursive scheme to our g function. Now the trick: using all the available magic at hand (aka Bird, Meertens and Malcolm) we apply a special rule, the universal property of fold, which is an equivalence between two definitions for a function g that processes lists, stated as:

    g [] = v
    g (x:xs) = f x (g xs)
    

    if and only if

    g = fold f v
    

    So, the universal property of folds states that:

        g = foldr k v
    

    where g must be equivalent to the two equations, for some k and v:

        g []     = v
        g (x:xs) = k x (g xs)
    

    From our earlier foldl designs, we know v == id. For the second equation though, we need
    to calculate the definition of k:

        g (x:xs)         = k x (g xs)        
    <=> g (x:xs) v       = k x (g xs) v      -- accumulator of functions
    <=> g xs (f v x)     = k x (g xs) v      -- definition of foldl
    <=  g' (f v x)       = k x g' v          -- generalize (g xs) to g'
    <=> k = \x g' -> (\a -> g' (f v x))      -- expand k. recursion captured in g'
    

    Which, substituting our calculated definitions of k and v yields a
    definition of foldl as:

    foldl :: (a -> b -> a) -> a -> [b] -> a    
    foldl f v xs =
        foldr
            (\x g -> (\a -> g (f v x)))
            id
            xs
            v
    

    The recursive g is replaced with the foldr combinator, and the accumulator becomes a function built via a chain of compositions of f at each element of the list, in reverse order (so we fold left instead of right).

    This is definitely somewhat advanced, so to deeply understand this transformation, the universal property of folds, that makes the transformation possible, I recommend Hutton’s tutorial, linked below.


    References

    • Haskell Wiki: Foldl as foldr
    • A tutorial on the universality and expressiveness of fold, Graham Hutton, J. Functional Programming 9 (4): 355–372, July 1999.
    • Malcolm, G. Algebraic data types and program transformation., PhD thesis, Groningen University.
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm reading the Monads chapter in Real World Haskell (chapter 14). A function is
I'm currently on chapter 4 of Real World Haskell, and I'm trying to wrap
Firstly, Real World Haskell , which I am reading, says to never use foldl
So I'm working through some initial chapter exercise of Real World Haskell and I
I'm on the I/O chapter of Real World Haskell. Monads aren't discussed in the
In chapter 15 of Real World Haskell, a type class is defined: class (Monad
I'm working through Real World Haskell one of the exercises of chapter 4 is
I'm following Real World Haskell, and am going through chapter 2, where the exercise
I almost finish the chapter 3 of Real World Haskell. The last exercise blocks
I'm going through Real world Haskell , and got to the example: -- file:

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.