4
votes

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.

3
Basically flip is sometimes unnecessary if you could use an infix notation of a function. Such as `subtract` 20. So you may do map (`subtract` 20) [1,2,3,4]. Or better map ((-) 20) [1,2,3,4]Redu
The parentheses are important – you can't "decompose" (flip subtract 20).molbdnilo

3 Answers

8
votes

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]
3
votes

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.

3
votes

flip has the following functionality: it applies a given function on the two given parameters in reverse order ("flipped").

Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c

That's how (flip subtract 20) becomes the function f(x) = 20-x, where (subtract 20) corresponded to g(x) = x-20.

Then, f is applied to each list item using the map function.