Reputation: 757
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?
Upvotes: 5
Views: 4240
Reputation: 54584
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)
Upvotes: 5
Reputation: 16262
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?
Upvotes: 14
Reputation: 31579
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!
Upvotes: 6
Reputation: 237080
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.
Upvotes: 3