Types
Type parameters
If a type has type parameters, they are enclosed in square brackets. If the name of a type parameter is unbound, it is a type variable. Otherwise, it is treated as a type argument.
Examples:
max ← # (numbers: list[integer]): integer – integer is a bound type
…
first ← # (items: list[item-type]): optional[item-type] – item-type is a variable
…
Like with regular variables, type parameters can also shadow existing names by
having an ! in the front:
some-weird-function ← # (items: list[!string]): string – string is a variable
Generic parameters are enclosed in brackets by themselves:
identity ← # (item: [item-type]): [item-type] item
Function types
Function types have the syntax #(parameter-types → return-type). For example:
fold ← #
(items: list[input-type],
initial-state: [state-type],
folder: #([state-type], [input-type] → [state-type]))
: [state-type]
…
Named parameters
It’s possible for a function type to have named parameters, which allows functions that are passed as parameters to be called with named arguments. For example:
folder: #(state: [state-type], next: [input-type] → [state-type])
– To call this function:
folder(state: …, next: …)
In this case, the function that’s passed in must support the required named
parameters. Thus, the folder parameter needs to be passed a function of the
form # (state, next) …. If this causes name clashes, then the parameters can
be simply declared as shadowing or be declared as labels (i.e.
# (state acc, !next) …).