Functions
Function declarations, local bindings, and the two branching forms. For literals, operators, and types see values and types; for the built-in functions see the prelude.
Declarations
A declaration is a name, zero or more parameters, =, and a body:
double x = x + xAn optional signature line may immediately precede it:
double : Int -> Intdouble x = x + xParameters desugar to nested lambdas, so a declaration is a name bound to an expression. A declaration with no parameters is a value:
port : Intport = 8080Recursion
Top-level declarations may be recursive, and mutually recursive across the
module — a declaration may reference any other, defined earlier or later.
let bindings likewise.
isEven : Int -> BoolisEven n = if n == 0 then True else isOdd (n - 1)
isOdd : Int -> BoolisOdd n = if n == 0 then False else isEven (n - 1)Recursing by accident
A top-level declaration shadows the prelude binding of the same name, and every operator desugars to a prelude binding. So this does not define addition:
add : Int -> Int -> Intadd x y = x + y+ lowers to add, the body calls the declaration itself, and the program
fails to compile:
analysis error: evaluation exceeded recursion limit (possible infinite recursion)Every name in the Builtin column of the operator table in the prelude carries the same trap. Check a declaration name against that column before taking it; nothing in the error points back at the operator that caused it. That example is compiled by CI and asserted to keep failing this way, so if the language ever removes the trap this page fails the build rather than teaching a footgun that is gone.
Currying and partial application
Every function of more than one parameter is curried; applying fewer arguments than the arity yields a function.
plus : Int -> Int -> Intplus x y = x + y
addFive : Int -> IntaddFive = plus 5Application is by juxtaposition and left-associative: f a b is (f a) b.
Lambdas
\params -> body is an anonymous function:
main : List Scrollmain = List.map (\name -> scroll { name = name, glyphs = [] }) [ "a", "b" ]A multi-parameter lambda \x y -> … desugars to nested single-parameter
lambdas.
let … in
let introduces local bindings, in scope in the body after in. Each binding
follows the declaration form and may carry a signature.
area : Float -> Floatarea r = let pi = 3.14159 in pi * r * rBindings may be mutually recursive and referenced in any order. let x = e in body is also valid on a single line.
if … then … else …
A conditional over a Bool. Both branches are required and must have the same
type.
label : Int -> Stringlabel n = if n > 0 then "positive" else "non-positive"if is equivalent to a two-arm case on True / False.
See also
- Values and types — literals, operators, types.
- Pattern matching —
caseand patterns. - Modules —
module,import, the search path. - Prelude — the standard-library functions.