Your basic understanding of what currying is is correct. Concretely, it is about transforming a function that takes its arguments as a tuple, such as for example
add :: (Int, Int) -> Int
add (x, y) = x + y
into a function that takes its arguments one at a time:
add' :: Int -> Int -> Int
add' x y = x + y
This scheme allows you to subject the now-curried function to partial application, i.e., applying it with some but not all of its arguments yet. For example we can have
succ :: Int -> Int
succ = add' 1
where we apply add'
to its first argument and yield a function that still expects the remaining argument.
The inverse transformation is called uncurrying and turns a function that takes it arguments "one by one" into a function that takes its arguments "all at once" as a tuple.
Both transformations can be captured by families of higher-order functions. That is, for binary functions there is
curry :: ((a, b) -> c) -> (a -> b -> c)
curry f = \x y -> f (x, y)
uncurry :: (a -> b -> c) -> ((a, b) -> c)
uncurry f = \(x, y) -> f x y
For ternary functions there is
curry3 :: ((a, b, c) -> d) -> (a -> b -> c -> d)
curry3 f = \x y z -> f (x, y, z)
uncurry3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
uncurry3 f = \(x, y, z) -> f x y z
And so forth.
Now let us have a look at your example:
2 * (\x y -> x * y) 2 3
Here you are multiplying the literal 2
with the result of an application of the function (\x y -> x * y)
that multiplies its two arguments x
and y
. As you can see, this function already takes its arguments "one by one". Hence, it is already curried. So, what is meant in your tutorial if they ask to write a curried version of this expression is beyond me. What we could do is write an uncurried version by having the multiplication function takes it arguments "all at once": (\(x, y) -> x * y)
. Then we get
2 * (\(x, y) -> x * y) (2, 3)
Now note that one could write (\(x, y) -> x * y)
as uncurry (*)
, which would give us
2 * uncurry (*) (2, 3)
If we also uncurry the first application (or actually applications, plural ;-)) of (*)
, we yield
uncurry (*) (2, uncurry (*) (2, 3))
I doubt whether this was the intention behind the exercise in your tutorial, but I hope this provides you some insight in currying and uncurrying.