Making sense of an auto curried language
Thursday, July 7, 2016
Partial Application and Currying are two common confusion points for people coming to autocurried languages for the first time. Often they'll say things like "this function takes 2 ints and returns an int". The reality is actually much simpler than that, though it may be a different way of thinking about the problem.
In an autocurried language every function takes one thing and returns one thing
In the following function it's obvious that we accept an
int and return an
int. In fact if we look at the signature for the function we see that it is
int -> int.
let add1 x = x + 1
But what about functions like
add that "take two arguments"?
let add x y = x + y
The fact that you can provide "two arguments" to a function is just syntactic sugar. What we've really done with that function is said that we have a function named
add that when given an
int will return a function that takes an
int and returns an
int. That's what those arrows are all about in the function signature
int -> int -> int.
We could write out the equivalent concept in C# if we manually curried the function.
Func<int, Func<int,int>> add = x => y => x + y; var three = add(2)(1);
Of course in C# this looks odd because of the parens surrounding each argument, but that's actually the same thing we're doing with the F# code. In F#, Haskell, and other ML dialect languages function application happens by the use of a space.
foo bar means apply the argument
bar to the function
foo, while the ALGOL family of languages uses parenthesis
Currying is the process of breaking a multi argument function into a function that takes an argument and returns a value, Partial Application is what happens when you apply a value to a function and the result of that application is another function.