Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the map function when the first argument uses flip

I am learning about higher-order functions from 'Learn You a Haskell for Great Good!' by Miran Lipovaca. I know that the flip function takes a function and returns a function like the original, but with the first two arguments flipped.

I don't fully understand how the following example with the map function works.

ghci> map (flip subtract 20) [1,2,3,4]
[19,18,17,16]

Map takes a function and applies it to each element of the list, resulting in a new list. But since flip is the function map takes, with parameters subtract 20 [1,2,3,4], would the resulting function be 20 subtract [1,2,3,4]?

I don't think this is correct since a value such as 19 is only produced if you type subtract 1 20. I am not sure how subtract would work in the above example to produce the output list.

like image 463
ceno980 Avatar asked Dec 07 '22 12:12

ceno980


2 Answers

No, here the function map :: (a -> b) -> [a] -> [b] takes is (flip subtract 20), this is the parameter you pass to map. So that means that:

map (flip subtract 20) [1,2,3,4]

is equivalent to:

[flip subtract 20 1, flip subtract 20 2, flip subtract 20 3, flip subtract 20 4]

flip :: (a -> b -> c) -> b -> a -> c is a function that takes a function and flips the parameters. So flip subtract 20 is semantically equivalent to \x -> subtract x 20. Our list is thus equivalent to:

[subtract 1 20, subtract 2 20, subtract 3 20, subtract 4 20]

subtract :: Num a => a -> a -> a is the "flipped" version of (-), so it is equivalent to:

[20 - 1, 20 - 2, 20 - 3, 20 - 4]

and thus equivalent to:

Prelude> map (flip subtract 20) [1,2,3,4]
[19,18,17,16]

A shorter version of the above expression is thus:

map (20 -) [1,2,3,4]
like image 102
Willem Van Onsem Avatar answered May 17 '23 06:05

Willem Van Onsem


But since flip is the function map takes...

No. map takes the function as its first parameter - which here is flip subtract 20. This is indeed a function, as we'll now see (if it wasn't, the compiler would raise an error because it's expecting a function here).

We'll start with subtract - which is actually defined as flip (-). This means flip subtract is simply (-), or:

flip subtract = \a b -> a - b

as opposed to

subtract = \a b -> b - a

So, by currying:

flip subtract a = \b -> a - b

and substituting in 20:

flip subtract 20 = \b -> 20 - b

So flip subtract 20 is indeed a function, which returns the result of subtracting its argument from 20. mapping this function over the list given gives the result shown.

like image 28
Robin Zigmond Avatar answered May 17 '23 06:05

Robin Zigmond