Partial application is a powerful concept in functional programming that allows you to fix some arguments of a function, producing a new function with a reduced arity. Haskell makes partial application very easy and natural thanks to its syntax and support for currying.
Currying is the technique of transforming a function that takes multiple arguments into a sequence of functions, each taking a single argument. In Haskell, all functions are automatically curried, which facilitates partial application.
Let’s look at an example of partial application in Haskell.
Suppose we have a simple function that adds three numbers:
addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z
Now, let’s say we want a new function that adds 5 and 7 to its argument. We can create this function by partially applying ‘addThree‘ to the arguments 5 and 7 like this:
addFiveAndSeven :: Int -> Int
addFiveAndSeven = addThree 5 7
Now, ‘addFiveAndSeven‘ is a new function that takes a single argument and adds 5 and 7 to it.
To further illustrate the concept, let’s break down the partial application of ‘addThree‘:
The type of ‘addThree‘ is ‘Int -> Int -> Int -> Int‘. When we apply it to an argument, say 5, we get a new function:
addThreeWithFive :: Int -> Int -> Int
addThreeWithFive = addThree 5
Now, ‘addThreeWithFive‘ is a function with signature ‘Int -> Int -> Int‘. Then, we can apply it to another argument, say 7:
addFiveAndSeven :: Int -> Int
addFiveAndSeven = addThreeWithFive 7
Finally, we get the desired ‘addFiveAndSeven‘ function.
Here is a graphical representation using a lambda calculus expression:
addThree = λx.(λy.(λz.x + y + z))
Applying ‘addThree‘ to 5:
addThreeWithFive = (λy.(λz.5 + y + z))
Applying it to 7:
addFiveAndSeven = (λz.5 + 7 + z)
Partial application can be quite useful for creating reusable components and for making code more readable.
In conclusion, partial application in Haskell allows you to provide a subset of the arguments required by a function, which results in a new function with fewer arguments. This technique is made possible and easy due to Haskell’s syntax and automatic currying of functions.