Type Ascriptions

While Flix supports local type inference, it can sometimes be useful to annotate an expression or a let-binding with its type. We call such annotations type ascriptions. A type ascription cannot change the type of an expression nor can it be used to violate type safety.

A type ascription can be placed after an expression:

(("Hello" :: "World" :: Nil) : List[String])

but it must be wrapped in parentheses to disambiguate it from other expressions.

It can also be placed on a let-binding parentheses:

let l: List[String] = "Hello" :: "World" :: Nil

Kind Ascriptions

Flix also supports kind ascriptions. Where a type ascription specifies the type of an expression, a kind ascription specifies the kind of a type.

We can use kind ascriptions on type parameters. For example:

def fst1[a: Type, b: Type](p: (a, b)): a = let (x, _) = p; x

Here we have specified that the kind of the two type parameters a and b is Type. We will typically never have to specify such kinds since they can inferred.

We can also provide kind ascriptions on algebraic data types:

enum A[t: Type] {
    case A(t, t)
}

and on traits:

trait MyTrait[t: Type] {
    // ...
}

We typically only use kind ascriptions for higher-kinded types.