Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Functions and Lambdas

Functions are values. The most common way to write one is a lambda.

Lambdas

\x -> x + 1

Lambdas can take multiple arguments:

\x y -> x + y

Rex also accepts the Unicode spellings λ and .

Annotating lambda parameters

You can annotate parameters when you need to force a specific type:

\(x: i32) -> x + 1

Application

Function application is left-associative:

f x y

is parsed as:

(f x) y

This is why parentheses are important when an argument is itself an application.

Functions returning functions (currying)

let add = \x -> (\y -> x + y) in
  (add 1) 2

Partial application

Because functions are curried, you can supply fewer arguments to get a new function back:

let add1 = (+) 1 in add1 41

Top-level functions (fn)

Top-level functions require an explicit type signature:

fn add : i32 -> i32 -> i32 = \x y -> x + y

This declares a function that takes an i32 and returns another function i32 -> i32.

Top-level fn declarations are mutually recursive, so they can reference each other:

fn even : i32 -> bool = \n ->
  if n == 0 then true else odd (n - 1)

fn odd : i32 -> bool = \n ->
  if n == 0 then false else even (n - 1)

even 10

Legacy fn header forms

The parser still accepts older forms that put parameter names/types in the header:

fn inc (x: i32) -> i32 = x + 1
fn inc x: i32 -> i32 = x + 1

For multiple parameters, the “named arrows” form looks like:

fn add x: i32 -> y: i32 -> i32 = x + y

fn constraints with where

Top-level functions can also have type-class constraints:

fn sum_list : List i32 -> i32 where Foldable List = \xs -> foldl (+) 0 xs

If you haven’t seen where constraints before, Section 2 covers them in detail.