The examples of plus
and plus'
are instructive. You see how the latter seems to have no arguments, at least on the left of the equals sign:
plus' :: Int -> Int -> Int
plus' = \x -> \y -> x + y
Let's make another pair of versions of increment (I'll name them after "bumping" a number—by 1) that go halfway to the final versions you gave:
bump :: Int -> Int
bump y = 1 + y
bump' :: Int -> Int
bump' = \y -> 1 + y
The analogy between these two definitions is just like the one between plus
and plus'
, so these should make sense, including the latter even though it has no formal arguments on the left-hand side of the equal sign.
Now, your understanding of bump'
, is exactly the same understanding you need to understand increment'
as you gave it in your question! In fact, we're defining bump'
to be equal to something which is exactly what increment'
is equal to.
That is (as we'll see shortly), the right-hand side of bump'
's definition,
\y -> 1 + y
is something that is equal to
plus 1
The two notations, or expressions, are two syntactic ways of defining "the function that takes a number and returns one more than it."
But what makes them equal?! Well, (as other answerers have explained) the expression plus 1
is partially applied. The compiler, in a way, knows that plus
requires two arguments (it was declared that way after all) and so when it appears here applied to just one argument, the compiler knows that it's still waiting for one more. It represents that "waiting" by giving you a function, saying, if you give one more argument, whether now or later, doing so will make this thing fully applied and the program will actually jump to the function body of plus
(thus computing x + y
for the two arguments that were given, the literal 1
from the expression plus 1
and the "one more" argument given later)
A key part of the joy and the value of Haskell is thinking about functions as things in themselves, which can be passed around and very flexibly transformed from one into another. Partial application is just such a way of transforming one thing (a function with "too many arguments", when you want to fix the value of the extras) into a function of "just the right many." You might pass the partially-applied function to an interface which expects a specific number of arguments. Or you might simply want to define multiple, specialized, functions based on one general definition (as we can define the general plus
and more specific functions like plus 1
and plus 7
).