Functions and application
| Define a function | |
| Application is a space | |
| Precedence | |
| if is an expression |
Define a function
A definition is a name, the arguments, an equals sign, and a body. No parentheses, no commas, no return keyword:
greet :: String -> String
greet name = "Hello, " ++ name ++ "!"
-- greet "Ada" == "Hello, Ada!"
The body is one expression. Where other languages need a block of statements, Haskell needs a let or a where to name the intermediate values.
Application is a space
Calling a function means writing it next to its argument. Juxtaposition binds tighter than any operator, so parentheses are needed around compound arguments:
show 42 -- "42"
show (42 + 1) -- "43"
max 3 9 -- 9
max 3 (min 9 4) -- 4
show turns a value into its textual form, and read goes the other way. The pair is how Haskell talks to the outside world without a formatting library.
Precedence
Arithmetic keeps the precedence you already know, and function application sits above all of it. The two rules that surprise newcomers are unary minus and the low precedence of $:
2 + 3 * 4 -- 14
negate 3 + 4 -- 1, application first
putStrLn $ show (2 + 3) -- same as putStrLn (show (2 + 3))
$ is a function that applies what is on its left to what is on its right, and it has the lowest precedence. It removes a trailing pair of parentheses, nothing more.
if is an expression
if produces a value, so the else branch is mandatory. Both branches must have the same type:
sign :: Int -> String
sign n = if n < 0 then "negative" else "not negative"
label = sign 5 ++ " number"
Because if is an expression, an
if without else is a
type error, not a style problem. When a chain of conditions grows
past two branches, guards read better, and lesson 10 covers them.
Next:
Currying and partial application
Article author: Arthur Isaev