niva Help

Unions

Tagged unions are the main way to achieve polymorphism in niva.

Unions are types that can be represented by one of several options at a time.

Declaration of union is like declaration of type + switch

union Shape = | Rectangle width: Int height: Int | Circle radius: Double

Pattern match

To work with a union, you first need to understand what form it is in.
Switch syntax is used for this.

constructor Double pi = 3.14 Double square = this * this Shape getArea -> Double = | this // "this" is Shape here | Rectangle => width * height |> toDouble | Circle => Double pi * radius square

Exhaustive

If you don't check all form options, this will be a compile time error.

Shape getArea -> Double = | this | Rectangle => width * height |> toDouble // | Circle => Double pi * radius square // Not all possible variants have been checked (Circle)

Instantiate

It is impossible to instantiate the root of the union, since then it is not clear what form it will correspond to.

But you can create branches, each union branch is no different from a regular type declaration.

x = Rectangle width: 2 height: 3 x getArea echo

Single line syntax

union Color = Red | Blue union Shape = Circle r: Int | Rectangle w: Int h: Int

Fields for Roots

Unlike other ML languages, union roots can contain fields

union Person name: String = | Student | Teacher

Both Student and Teacher have a name field here.
This simplifies 2 things at once:

  1. There is no need to repeat common fields for each union's branch.

  2. You don't need to pattern match the Person to gain access to the name field

Printer printPerson: p::Person = p name echo

Include one union into another

union Vehicle = | ^Car | Plane | Ship union Car = RaceCar | Truck | PassengerCar

Now Vehicle is Car | Plane | Ship or RaceCar | Truck | PassengerCar | Plane | Ship

So now u can pattern match it like

Vehicle printSpeed = | this | Car => "medium" echo | Plane => "fast" echo | Ship => "slow" echo

Inside Car branch we can match each Car branch:

Vehicle printSpeed2 = | this | Plane => "fast" echo | Ship => "slow" echo | Car => [ | this | RaceCar => "fast" echo | Truck => "slow" echo | PassengerCar => "medium" echo ]

Or the last variant - plain match on every branch:

Vehicle printSpeed3 = | this | Plane => "fast" echo | Ship => "slow" echo // Car | RaceCar => "fast" echo | Truck => "slow" echo | PassengerCar => "medium" echo

IDE support

You can try to send match message to any value of union root type to generate all the branches for pattern matching.
Or match deep to generate matching for every possible nested branch too, like in the last example

Homework

Create a well known example with Cat Dog, all of them are Animal. Animal can eat food. Food are Meat or Vegetable

Last modified: 21 October 2024