I gave a talk called Some(‘F#’) is Better Than None at Winnipeg Code Camp on January 28, 2017. The talk was catered toward developers who have never looked at F# or those who never considered F# as being a useful prototyping tool.
During the talk I made a brief mention to currying and partial application. After the talk I received a great question along the lines of: if every function only takes one argument, how is it we are able to pass multiple arguments to a function?
Currying is the process of transforming a function which takes multiple arguments into a sequence of functions where each new function takes only one argument. If we were to write the function:
let addThreeNumbers x y z = x + y + z
This function looks like it takes three arguments, however the signature of addThreeNumbers is converted to int -> int -> int -> int. We can read the function signature as:
addThreeNumbers has type of
int goes to
int goes to
int goes to
int. The last type in the signature denotes the return type of the function.
addThreeNumbers function we defined earlier, we can call the function as:
addThreeNumbers 1 2 3
Since we are passing in the full number of arguments the function evaluates immediately giving us the result of 6.
As we are passing in arguments, the function applies what it can with the arguments given. Each time we add an argument it peels off the leading type ->, eventually reaching the point where there is nothing left to apply which then evaluates the result.
// int -> int -> int -> int let addThreeNumbers x y z = x + y + z let result = addThreeNumbers 1 2 3 // can be thought of as let result' = (((addThreeNumbers 1) 2) 3) // You can also apply the arguments in steps and create // intermediate functions. // addTwoNumbersWith1 :: int -> int -> int let addTwoNumbersWith1 = addThreeNumbers 1 // addOneNumberWith1and2 :: int -> int let addOneNumberWith1and2 = addTwoNumbersWith1 2 // six :: int let six = addOneNumberWith1and2 3
Currying and partial application are very powerful features. Currying is the process of transforming a function which takes multiple arguments into a sequence of functions which take one parameter. Applying arguments to a curried function peels off a function from the sequence. This allows you to build reusable functions.