Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

type signature of uncurry function

Tags:

haskell

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?

like image 336
CathyLu Avatar asked Jan 21 '11 01:01

CathyLu


People also ask

What does uncurry do?

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) .


4 Answers

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 Nums 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?

like image 152
Zach L Avatar answered Sep 30 '22 16:09

Zach L


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!

like image 24
Tom Crockett Avatar answered Sep 30 '22 15:09

Tom Crockett


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)
like image 34
Landei Avatar answered Sep 30 '22 15:09

Landei


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.

like image 36
Chuck Avatar answered Sep 30 '22 17:09

Chuck