简体   繁体   中英

Haskell: applying flip twice (type of flip flip)

I am learning Haskell along some basic functions. I was doing some exercises with Flip, which takes a function of two arguments and evaluates the result flipping the order of the arguments. Consider the function flip flip , I would have thought, following the definition of flip, that it flipped the arguments twice, evaluating the original function with the parameters in the original order. When I checked this assumption with ghci checking the function type, it yielded:

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

I don't understand why this is the function type of flip flip. It takes parameter b and parameter (a -> b -> c) and yields a function a -> c. Why is this the case ? I would really appreciate an explanation since I am at lost with this. Thanks in advance

Flipping twice would be \\f -> flip (flip f) , or flip . flip flip . flip . This would indeed have the type (a -> b -> c) -> (a -> b -> c) .

What you are doing here instead is applying flip on the flip function, ie flipping flip 's argument order. So if we start with

flip :: (a -> b -> c) -> b -> a -> c
-- and, as the type of the argument
flip :: (a' -> b' -> c') -> b' -> a' -> c'

then if we match the types

a = (a' -> b' -> c')
b = b'
c = a' -> c'

we get the result

flip flip :: b' -> (a' -> b' -> c') -> (a' -> c')

Let's look at the types:

flip :: (a -> b -> c) -> b -> (a -> c)
flip :: (d            -> e ->  f     ) -> e ->  d            ->  f
flip flip ::                              b -> (a -> b -> c) -> (a -> c)

In other words, flip reverses the first two arguments of its argument, and the first two arguments of flip are the function to flip and the second argument to that function. So instead of taking arguments in the order 'function', 'second argument', 'first argument', the order becomes 'second argument', 'function', 'first argument' when you flip it.

If you want to flip, and then flip back, you do something like this:

doubleflip x = flip (flip x)

Or equivalently:

doubleflip = flip . flip

The (.) operator feeds the output of the right-hand side into the left-hand side.

You do not apply the flip function twice. If you want to apply flip twice, you are looking for:

 :: (b -> a -> c) -> b -> a -> c

What you here do is flipping the flip function. So it takes flip as the function to flip .

We can resolve the type of flip 1 flip 2 (I here use subscripts to make it clear to which flip we are referring) as:

flip1 :: (a -> b -> c) -> b -> a -> c
flip2 :: (d -> e -> f) -> e -> d -> f

Since flip 2 is the parameter of flip 1 , so that means that the type of flip 2 is the same type of the parameter of flip 1 , so that means that:

        a       -> (b ->    c    )
~ (d -> e -> f) -> (e -> (d -> f))

Hence that means that a ~ (d -> e -> f) (the type a is the same as d -> e -> f ), b ~ e and c ~ (d -> e) . So the type of the function flip 1 flip 2 is the type of the output type of flip 1 , but with the equivalences, so that means that:

flip1 flip2 :: b -> a -> c
flip1 flip2 :: e -> (d -> e -> f) -> (d -> e)

We basically thus made a function that first takes the second parameter, then takes the function, and then the first parameter, and then calls that function with the flipped parameters. So if flip2 = flip flip , it is implemented like:

flip2 :: e -> (d -> e -> f) -> (d -> e)
flip2 y f x = f x y

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