简体   繁体   中英

How does the foldr function in haskell work in this case?

So I'm new to haskell and I kind of encountered this following expression which i don't quiet get how it works: foldr (.) (+3) [(*2), (+5)] 13 it gives out the result: 42 now i know that foldr normally works in an example like: foldr (+) 0 [1,2,3] like: (1+(2+(0+3))) but with adding another function (.) I kind of got confused. So please if any of you could explain to me exactly how haskell interprets this expression that would be great, thanks!

Comments might have already solved this for you. However, if not:

(.) is function composition:

f . g
= \x -> f $ g $ x
= \x -> f (g x).

Forms like (* 2) are sugar for functions of the form \\x -> x * 2

Now, observe that

foldr op base [a,b]

is the same as

a `op` (b `op` base)

of course, this works for higher numbers of arguments as well. For instance,

foldr (+) 0 [1,2,3,4,5]

is just

1 + 2 + 3 + 4 + 5 + 0

In your case, you ask about

foldr (.) (+3) [(*2), (+5)]

which is (for Integer )

(*2) . (+5) . (+3)
= \x -> (*2) $ (+5) $ (+3) $ x
= \x -> (*2) $ (+5) $ x + 3
= \x -> (*2) $ x + 3 + 5
= \x -> (x + 3 + 5) * 2
= \x -> x*2 + 16

and so

foldr (.) (+3) [(*2), (+5)] 13
= (\x -> x*2 + 16) 13
= 13*2 + 16
= 26 + 16
= 42

foldr fz can be seen as replacing the "cons" (:) of the list with f , and the empty list with z . This thus means that foldr fz [x 1 , x 2 … x n ] is equivalent to fx 1 (fx 2 ( … (fx n z) … ))

[(*2), (+5)] is syntactical sugar for (:) (*2) ((:) (+5) []) , so we can replace this with: (.) (*2) ((.) (+5) (+3)) , which is a verbose form of (*2) . (+5) . (+3) (*2) . (+5) . (+3) (*2) . (+5) . (+3) . This is thus a function. If we make a function application with this function and 13 as argument, we get:

   ((*2) . (+5) . (+3)) 13
-> ((*2) . (+5)) 16
-> (*2) 21
-> 42

foldl fz [x 1 , x 2 … x n ] is equivalent to f (… (f (fzx 1 ) x 2 ) … ) x n . So here that means foldl (.) (+3) [(*2), (+5)] is equivalent to (.) ((.) (+3) (*2)) (+5) , or less verbose (+3) . (*2) . (+5) (+3) . (*2) . (+5) (+3) . (*2) . (+5) . If we evaluate this for 13 , we obtain:

   ((+3) . (*2) . (+5)) 13
-> ((+3) . (*2)) 18
-> (+3) 36
-> 39

In Haskell (and in lambda calculus) you can do Eta reduction

In the example you shown, the long way to write would be:

foldr (\f h -> f . h) (\x -> x+3) [(\x -> x*2), (\x->x+5)] 13

Now you can apply Eta reduction one by one like this:

(\f h -> f . h)
(\f -> (f.))
(.)

next:

(\x -> x+3)
(+3)

(\\x -> x*2), (\\x->x+5) are so similar to (+3)

so finally you get you equivalent expression:

foldr (.) (+3) [(*2), (+5)]

and that means, compose each function, and when the list is empty, apply (+3)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM