1
votes

I am learning higher-order functions from 'Learn You a Haskell for Great Good!' by Miran Lipovaca.

For the following function flip which takes a function and returns a function with the first two arguments flipped:

flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = g
   where g x y = f y x

I don't exactly understand what f and g are. Are they two different functions? Similarly, in the where binding, what exactly does g x y = f y x mean?

2

2 Answers

5
votes

In the syntax:

myFunction x = x + 2

things on the left hand side of the equal sign, x, are treated as "parameters". You can use them on the right hand sign of the equal sign to state what you want the result to be.

This syntax defines a function myFunction, with single parameter x.

So here we have:

flip' f = g

This defines a function flip', with single parameter f.

We have another definition, as well:

g x y = f y x

This defines a function g, with two parameters, x and y.

So when we say:

flip' f = g
  where
    g x y = f y x

We are saying that the result of flip f is the function g, where g is defined as g x y = f y x.

In case the short variable names are confusing you, here is the same function with some of the names swapped for clarity:

flippity flop = glop
  where
    glop x y = flop y x

See if you can understand what flippity does, and see if you can see how it is the same as flip', just with different internal parameter and helper function names.

Remember also in Haskell that we can always replace function calls by their body, for the most part. So we can rewrite that as:

flippity flop = glop
  where
    glop = \x y -> flop y x

-- replace glop with its definition

flippity flop = \x y -> flop y x

So we can see that flippity is a function that takes a function flop and returns a new function, \x y -> flop y x.

5
votes

f is flip''s input (the function you want to flip), g is flip's output (the flipped function it will return).

The where clause is simply defining what g is; that is, defining a function that simply calls f with its arguments reversed.

You could avoid naming g at all by simply having flip' return a lambda:

flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = \x y -> f y x