One of the basic concepts in functional programming that you'll need to learn to use Haskell is that functions are just a kind of value, definitions just name things. It's not like procedural languages where there's a sharp distinction made between functions and variables and function definitions are completely different from variable definitions.
So a variable definition like
addOne :: Int -> Int
addOne = add 1
is just adding a name for the expression add 1
, so you can refer to it as addOne
. It's identical to a variable declaration.[1] The fact that the value of that variable is a function is almost incidental, from Haskell's perspective.
Your add
definition:
add :: Int -> (Int -> Int)
add x y = x + y
is also a variable definition. It's a bit of syntax sugar Haskell provides for:
add :: Int -> Int -> Int
add = \ x -> \ y -> x + y
on the theory that it's easier to read. But it's still just sugar; you never need it (except see [1] below) like you would in other languages.
[1]: The dreaded monomorphism restriction also comes into play here. The idea is just: in a function definition, the RHS will be executed by the computer many times (as many times as you call the function). You are probably aware of this from other languages. In a monomorphic variable definition, the RHS will be executed at most once, which is also similar to how other languages work. However, a polymorphic variable often ends up acting like a function definition, with the RHS being executed as many times as the value of the variable is accessed. So Haskell dis-allows polymorphic definitions unless you have a polymorphic type signature (so you say "I know what I'm doing, allow this variable to be polymorphic") or you have arguments on the left-hand side (so it "looks like" the RHS should be executed many times).