Type parameters

Type parameters for functions

Functions can declare type parameters. Below, swap can work on a pair of any type.

main void() a (nat, nat) = 1, 2 log swap a b (string, string) = "world", "hello" log swap b swap[t] (t, t)(a (t, t)) a.b, a.a

In swap a , nat is substituted for t.
In swap b , string is substituted for t.

A type parameter must be consistent, so swap would not work on a (nat, string).

Within the body of swap, t is treated as "any type"; it can't be passed to another function unless that function also takes it as a type parameter. (The tuple getters a and b do so.)
In the next section, Specs, we'll see how to add more useful operations on type parameters.

Explicit type arguments

An explicit type argument can be specified using @.

main void() a (nat, nat) = 1, 2 log swap@nat a b (string, string) = "world", "hello" log swap@string b swap[t] (t, t)(a (t, t)) a.b, a.a

If there are multiple type arguments, put them in parentheses.

main void() a (nat, string) = 1, "foo" log swap@(nat, string) a swap[t, u] (u, t)(a (t, u)) a.b, a.a

You should almost never use explicit type arguments, but they can help diagnose errors if Keen doesn't know what function you're trying to call. Then remove the explicit type arguments once it's working.

Type parameters for types

A type can itself have type parameters.

main void() a nat ranker = best: 7, worst: 13 log worst invert a ranker[t] record best t worst t invert[t] t ranker(a t ranker) a.worst, a.best

Types with type parameters use a suffix syntax: t ranker is a ranker of t, just like t[] is an array of t.
The suffixes can stack, so you can have a t ranker[] (array of rankers) or a t[] ranker (ranker arrays).

Type annotations such types may require parentheses, as in foo::(nat ranker) .

If there are multiple type parameters, write them like a tuple, as in (nat, string) pair .

main void() a (nat, string) pair = 1, "foo" log a.a, a.b pair[t, u] record a t b u