Currently I am trying to learn Haskell with the book 'Learn You a Haskell' and I'm trying to understand the implementations of the flip
function in chapter 5 . The problem is that the author states that if gxy = fyx
is valid, then fyx = gxy
must be also true. But how and why does this reversal affects the two function definitions?
I know how currying works and I also know that the ->
operator is right-associative by default so the type declarations are in fact the same. I also understand the functions apart from each other but not how the reversal of gxy = fyx
is in relation with this.
first flip function
flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = g
where g x y = f y x
second flip function
flip' :: (a -> b -> c) -> b -> a -> c
flip' f y x = f x y
I think the argument the author has in his head got wildly abbreviated to the point that it's not even sensical. But here is my guess about the reasoning. We start with the first definition:
flip f = g where g x y = f y x
Now we observe that this is a curried thing, and we use all the discussion of associativity of (->)
and junk to write the same thing, but with two extra arguments to f
. Like this:
flip f = g where g x y = f y x
Now we have the equation that he called out as going both ways: gxy = fyx
and vice versa. We can rewrite the body of the flip
using this equation, like this:
flip f x y = where g x y = f y x
Since the body of the definition no longer mentions g
, we can delete it.
flip f x y = f y x
And now we're pretty much there. In the final definition, the author has swapped the names x
and y
everywhere. I don't know why they chose to do so, but it is a legal move that you can make in equational reasoning, so no problem there. Doing so gives us their final equation:
flip f y x = f x y
flip
takes a function and returns the flipped version of the function. One way to define flip'
is to include the application in the definition itself, since
flip' f y x = f x y ===> flip' f y = \x -> f x y
===> flip' f = \y -> \x -> f x y
That is, flip' f
is a function that applies f
to its own arguments in reverse order.
The second definition simply gives the anonymous function \\y -> \\x -> fxy
a name first, then uses that name as the definition of flip' fxy
.
===> flip' f = g where g = \y -> \x -> f x y
===> flip' f = g where g y = \x -> f x y
===> flip' f = g where g y x = f x y
That is, flip' f
is some function g
, where g
is defined to apply f
to the arguments of g
in reverse order.
The definitions gxy = fyx
and gyx = fxy
are equivalent up to alpha conversion . In both cases, f
is a free variable in the definition of g
; g
is as a closure over the f
argument to flip'
.
If you are here looking for what flip does:
Prelude> pow x y = x ^ y
Prelude> pow 2 3
8
Prelude> flip pow 2 3
9
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.