How does foldr work?

后端 未结 10 2067
别跟我提以往
别跟我提以往 2020-12-04 06:37

Can anybody explain how does foldr work?

Take these examples:

Prelude> foldr (-) 54 [10, 11]
53
Prelude> foldr (\\x y -> (x+y)/2) 54 [12, 4,         


        
10条回答
  •  余生分开走
    2020-12-04 07:18

    It helps to understand the distinction between foldr and foldl. Why is foldr called "fold right"?

    Initially I thought it was because it consumed elements from right to left. Yet both foldr and foldl consume the list from left to right.

    • foldl evaluates from left to right (left-associative)
    • foldr evaluates from right to left (right-associative)

    We can make this distinction clear with an example that uses an operator for which associativity matters. We could use a human example, such as the operator, "eats":

    foodChain = (human : (shark : (fish : (algae : []))))
    
    foldl step [] foodChain
      where step eater food = eater `eats` food  -- note that "eater" is the accumulator and "food" is the element
    
    foldl `eats` [] (human : (shark : (fish : (algae : []))))
      == foldl eats (human `eats` shark)                              (fish : (algae : []))
      == foldl eats ((human `eats` shark) `eats` fish)                (algae : [])
      == foldl eats (((human `eats` shark) `eats` fish) `eats` algae) []
      ==            (((human `eats` shark) `eats` fish) `eats` algae)
    

    The semantics of this foldl is: A human eats some shark, and then the same human who has eaten shark then eats some fish, etc. The eater is the accumulator.

    Contrast this with:

    foldr step [] foodChain
        where step food eater = eater `eats` food.   -- note that "eater" is the element and "food" is the accumulator
    
    foldr `eats` [] (human : (shark : (fish : (algae : []))))
      == foldr eats (human `eats` shark)                              (fish : (algae : []))))
      == foldr eats (human `eats` (shark `eats` (fish))               (algae : [])
      == foldr eats (human `eats` (shark `eats` (fish `eats` algae))) []
      ==            (human `eats` (shark `eats` (fish `eats` algae) 
    

    The semantics of this foldr is: A human eats a shark which has already eaten a fish, which has already eaten some algae. The food is the accumulator.

    Both foldl and foldr "peel off" eaters from left to right, so that's not the reason we refer to foldl as "left fold". Instead, the order of evaluation matters.

提交回复
热议问题