Union Types
type
statement
Union Types are declared with type
keyword and variants are described one or more types separated by |
.
type T = Int | String;
Using this T
,
Int
values and String
values can be same type values.
This is convenient to construct an array of Int
or String
(i.e. Array<T>
).
You can represent more complicated types with struct
.
struct A { a: Nat }
struct B { b: String }
struct C { c: Array<String> }
type T = A | B | C;
NOTE
Union Types is like union-sets, and not Sum Types (or disjoint union). For example,
type T = Int | Int;
this equals to just Int
exactly,
because nobody distinguish left Int
from right one.
NOTE
Union Types define subtypes. In primitive, cumin defines the following subtype system:
Nat <: Int <: Float
and induces the following implicit type-cast:
Nat -> Int -> Float
And, when type T = A | B;
,
A <: T,
B <: T
holds on.
So, you can cast A -> T
and B -> T
, but we don't cast them implicitly.
In next section, we will show how to cast them.
Casting for Union Types
The names of union types can be casting functions (or injection).
type T = Int | String;
let x: Int = 2;
let t = T(x); // Int -> T
let s = T("hello"); // String -> T
struct A { a: Nat }
struct B { b: String }
struct C { c: Array<String> }
type T = A | B | C;
let t = T(A(1)); // A -> T
let u = T(C { c = [] }); // C -> T
If you mind of the mount of parenthesis, we prepared a syntax-sugar.
Composite Applying Syntax
A.B(x)
will be A(B(x))
.
A.B{x = y}
will be A(B{x=y})
.
struct A { a: Nat }
struct B { b: String }
struct C { c: Array<String> }
type T = A | B | C;
let t = T.A(1); // T(A(1))
let u = T.C{c=[]}; // T(C { c = [] })
Yay!