uncurry f=\(a,b)->f a b
uncurry
converts a curried function to a function on pairs, but the function above just converts it to a curried function f a b
. Doesn't that contradict the definition of the uncurry
function?
uncurry converts a curried function to a function on pairs. All it does is it takes a function (a -> b -> c) and returns a function that takes the parameters as a tuple. So phy does the same thing as $ , but instead of f $ x or ($) f x you call it like phy (f, x) .
What pelotom and Chuck said is 100% right. I think you just got a little confused at some point about curry vs uncurry and function definitions.
We know that a curried function is one like:
add x y = x + y
It's definition would be:
add :: (Num a) => a -> a -> a
Add takes a Num
, and returns a function that takes a Num
and returns a Num
.
By having it this way, we can get a partially applied function, like
add3 = add 3
Thanks to add
being curried, when we can pass just one parameter (in this case, 3), we can get back a function that takes a Num
and returns a Num
.
>add3 5
8
Uncurried functions takes tuples, or grouped together values, like (1,2). (Note, tuples don't have to pairs. You can have a tuple of the form of (1,2,3,4,5). Just regular old uncurry deals with specifically pairs). If we changed our add to be uncurried, it'd be:
add :: (Num t) => (t, t) -> t
add (x, y) = x + y
Which takes a tuple of two Num
s and returns a Num. We can't partially apply this like we did with add as a curried function. It needs both parameters, passed in a tuple.
Now, onto the uncurry function! (If you want to know the type of a function, use :t <some function>
in GHCi, or use Hoogle).
uncurry :: (a -> b -> c) -> ((a, b) -> c)
uncurry f=\(a,b)->f a b
So what do we know from this? It takes f, which we notice from the definition is a curried function from (a->b->c), and it returns a uncurried function ((a,b)->c).
If we feed uncurry our curried add (remember: add x y
), what do we get back?
We get an anonymous function, or lambda function, that takes a tuple, and applies the values of the tuple, a
and b
, to our function, add
.
f a b
doesn't mean we get a function -- you'd see a ->
if that was the case. We just get the value of f
with a
and b
.
It's kind of like if we did this by hand:
tupleAdd (a,b) = add a b
But uncurry
does this all for us, and we can just continue along with our brand new uncurried form of our originally curried function.
Cool, hunh?
Another way of writing this definition so it's clearer what's going on would be:
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f = \(a, b) -> (f a) b
The variable f
has type a -> b -> c
, i.e. it is a curried function, and uncurry g
for some curried function g
has the type (a, b) -> c
, i.e. an uncurried function.
Remember that when x
and y
are terms, x y
means apply the function x
to y
. And f a b
(or (f a) b
) means apply the function f
to the argument a
, producing a function of type b -> c
, then immediately apply this function to b
, producing a result of type c
. So the right-hand side of this definition is just showing how to unpack the components of a tuple argument and apply them to a curried function, which is exactly the process of uncurrying!
You can write a function which behaves the same way (and with the same signature) without a lambda:
uncurry' :: (a -> b -> c) -> ((a, b) -> c)
uncurry' f (a,b) = f a b
I think this version is easier to read. If you have a tupel and a function which takes two single values (or more exact, which takes one value and returns a function that takes the next value), the uncurry' function does the "unwrapping" of the tuple for us.
Generally if you see something like
f x y z = x + y + z
it's the same as
f = \x y z -> x + y + z
or
f x = \y -> (\z -> x + y + z)
I think you're misreading. It does indeed return a function on pairs. That's what the \(a,b)->
part means — it defines an anonymous function that takes a pair and performs the given function on the values in that pair.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With