Currying #
Functional programs traditionally define functions in curried form (for a definition, we refer to the dedicated section).
In Haskell #
Syntax #
A Haskell function can (in theory) take a tuple as argument.
Example.
power :: (Int, Int) -> Int power (x,y) = x^y
However, functions in curried form are usually preferred, because they are more versatile.
Example. The function above in curried form can be written:
power :: Int -> (Int -> Int) power = \x -> (\y -> x^y)or equivalently:
power :: Int -> (Int -> Int) power x = \y -> x^yor equivalently (and more commonly):
power :: Int -> (Int -> Int) (power x) y = x^y
Syntax. The
->operator associates to the right, meaning thatA -> (B -> C)can be written
A -> B -> CSimilarly, function application associates to the left, meaning that
(f x) ycan be written
f x ySo the function above is normally written:
power :: Int -> Int -> Int power x y = x^y
Write in Haskell the curried form of the function $\textit{applySwapped}(x,f)$, where
- $f$ is a function that maps strings to Boolean values,
- $x$ is a string,
- $\textit{applySwapped}(x,f) = f(x)$.
applySwapped :: String -> (String -> Bool) -> Bool
applySwapped x f = f x
Consider the following Haskell program.
aFunction :: Integer -> Integer -> Integer
aFunction x y = y - x
anotherFunction = aFunction 1
- Which of the following types is correct for the function
anotherFunction?
Integer -> Integer -> Integer(Integer -> Integer) -> IntegerInteger -> Integer
- What does this function do?
-
Integer -> Integer -
It maps an integer
ytoy - 1.
Consider the following Haskell program, where the function ord :: Char -> Int maps a character to its Unicode number.
aFunction i j f c = anotherFunction i j (f c)
anotherFunction :: Int -> Int -> Int -> Int
anotherFunction i j k = (i * j) + k
main = print $ aFunction 10 3 ord 'V'
-
The Unicode number of
Vis86. So what does the methodmainprint? -
Which of the following types is correct for the method
aFunction?
Int -> Int -> Char -> Int -> Char -> Int(Int -> Int) -> Char -> Int -> Char -> IntInt -> (Int -> Char) -> Int -> Char -> IntInt -> Int -> (Char -> Int) -> Char -> IntInt -> Int -> Char -> (Int -> Char) -> Int(Int -> Int) -> (Char -> Int) -> Char -> Int(Int -> Int) -> (Char -> Int) -> Int -> Char -> Int(Int -> Int) -> (Char -> Int -> Char) -> Int(Int -> Int) -> (Char -> Int -> Char) -> Char -> Int(Int -> Int) -> (Char -> Int -> Char) -> Int -> Char -> Int
- 116
Int -> Int -> (Char -> Int) -> Char -> Int
Write in curried form the function $\textit{applyAndCompose}(f,g,x)$, where:
- $f$ is the curried form of a function $f’\colon \mathbb{Z} \times \text{String} \to \mathbb{Z}$,
- $g$ is a function that maps integers to Booleans,
- $x$ is an integer, and
- $\textit{applyAndCompose}(f,g,x)$ is the composition of $f(x)$ and $g$.
applyAndCompose :: (Integer -> String -> Integer) -> (Integer -> Bool) -> Integer -> String -> Bool
-- the RHS can also be written g . f x (parentheses are redundant here)
applyAndCompose f g x = g . (f x)
Explanation.
We know that:
- $f$ is the curried form of a function $f’\colon \mathbb{Z} \times \text{String} \to \mathbb{Z}$,
- $g$ is a function that maps integers to Booleans, and
- $x$ is an integer.
From these descriptions, we can infer the following Haskell types:
- $x$ has type
Integer. - $g$ has type
Integer -> Bool. - $f’$ has type
(Integer, String) -> Integer. - So $f$ (which is the curried version of $f’$) has type
Integer -> String -> Integer. - Therefore $f(x)$ has type
String -> Integer. - So the composition of $f(x)$ and $g$ (written $g \circ f(x)$, or
g . (f x)in Haskell) has typeString -> Bool.
Infix notation #
Some native Haskell functions are written in infix notation.
These are often binary operators, like + (sum of two numbers) or && (Boolean conjunction).
These functions are implicitly in curried form.
Example. The function
&&has typeBool -> Bool -> Bool.
Like any function in curried form, we can call an infix function with its “first argument” only.
Example.
2 -is the function that subtracts a number from two.
This is an alternative syntax for\x -> 2 - x
Surprisingly, in some contexts, an infix function can also be called with its “second argument” only (whereas a prefix function cannot).
Example.
- 2is an alternative syntax (allowed in certain contexts only) for
\x -> x - 2
Infix to prefix #
An infix function can be used as a regular (i.e. prefix) one, by surrounding it with parentheses.
Examples.
an expression an equivalent expression 2 + 3(+) 2 3True && True(&&) True True
This is helpful in contexts where the infix form cannot be used.
For instance,
we can pass the function && to another function by surrounding it with parentheses.
We can also define an infix function, as long as its name consists of so-called “symbol characters”. This means not letter, number, etc. (the full list symbol characters can be found here). In this case, the type declaration must use parentheses.
Example. The program below define a function
^^^in infix form.(^^^) :: Integer -> Integer -> Bool x ^^^ y = x > 0 && x < y main = print $ 2 ^^^ 4
Prefix to infix #
A curried function in prefix form can be used as an infix one, by surrounding it with `.
Examples.
prefix form equivalent infix form power 2 32 `power` 3isPrefixOf "foo" "foobar""foo" `isPrefixOf` "foobar"