Functions make up the backbone of the Vehicle language.

Function types

The function type is written A -> B where A is the input type and B is the output type. For example Rat -> Bool is the type of functions from a rational number to a boolean value.

As is standard in functional languages, the function arrow associates to the right so A -> B -> C is therefore equivalent to A -> (B -> C). The type A -> (B -> C) is a function that takes something of type A and returns a function from B to C. In contrast (A -> B) -> C is a function that takes another function from A -> B as its first argument and returns something of type C.

Function application

As in most functional languages, function application is written by juxtaposition of the function with its arguments. For example, given a function f of type Rat -> Bool -> Rat and arguments x of type Rat and y of type Bool, the application of f to x and y is written f x y and this expression has type Bool.

This is unlike imperative languages such as Python, C or Java where you would write f(x,y).

Function declarations

Declarations may be used to define new functions. A declaration is of the form

<name> : <type>
<name> [<args>] = <expr>

For example the function increment that takes adds 1 to a natural number may be defined as follows:

increment : Nat -> Nat
increment x = x + 1

and can then be used later in the specification.


Alternatively, anonymous functions can be declared using the \x -> ... notation, e.g.

\x -> x + 1

is also a function that increments its input. Lambda functions can be applied in the same way as normal, for example:

(\x -> x + 1) 1

will evaluate to 2.

Variables bound by lambdas may optionally be annotated by their type as follows:

\(x : Nat) -> x + 1

Multiple parameter lambdas are also supported:

\x y -> x + 2 * y