Currying and Partial Application
Prerequisites: Defining functions
Every Haskell function takes exactly one argument. A "two-argument" function is really a function that takes the first argument and returns a function that takes the second. This is called currying.
The type Int -> Int -> Int actually means Int -> (Int -> Int): ->
groups to the right.
Partial application
Because of currying, you can give a function some of its arguments and get back a function waiting for the rest:
add :: Int -> Int -> Int
add x y = x + y
addTen :: Int -> Int
addTen = add 10
main :: IO ()
main = do
print (addTen 5)
print (map (add 100) [1, 2, 3])
print (map (max 5) [1, 7, 3, 9])
15
[101,102,103]
[5,7,5,9]
add 10 is a complete value of type Int -> Int. Partial application
makes it easy to build new functions from existing ones without writing
lambdas.
Operator sections
Operators can be partially applied too, by wrapping them in parentheses with one side missing — a section:
main :: IO ()
main = do
print (map (* 2) [1, 2, 3])
print (map (2 ^) [1, 2, 3])
print (map (^ 2) [1, 2, 3])
print (map (10 -) [1, 2, 3])
print (filter (> 3) [1, 5, 2, 8])
print (map (`div` 2) [10, 11, 12])
[2,4,6]
[2,4,8]
[1,4,9]
[9,8,7]
[5,8]
[5,5,6]
(* 2)means\x -> x * 2;(2 ^)means\x -> 2 ^ x. Which side is missing decides where the argument goes.(- 1)is not a section — it's the number minus one. Usesubtract 1instead.
Why it matters
Currying is why Haskell code tends to put the "configuration" arguments
first and the data last: map f xs, filter p xs, take n xs. That
order makes partial application natural:
firstThree :: [a] -> [a]
firstThree = take 3
main :: IO ()
main = do
print (firstThree "Haskell")
print (firstThree [10, 20, 30, 40, 50])
"Has"
[10,20,30]
Defining a function without naming its argument, like
firstThree = take 3, is called point-free style.
curry and uncurry
uncurry turns a curried function into one that takes a pair, and
curry does the opposite:
main :: IO ()
main = do
print (uncurry (+) (3, 4))
print (map (uncurry max) [(1, 5), (8, 2)])
print (curry fst 'a' 'b')
7
[5,8]
'a'