Case types (unions, variants)

Single cases

A new case x is defined with

case x

and when it has a parameter with

case y(number)

Examples:

With case several things are defined at once:

When a case has a parameter, it is enforced that the parameter has the specified type. After defining y(number) it is e.g. never possible to put anything else into the case than a number.

Private cases

If a case is declared as private, the constructor cannot be called from outside the module. That way the module has full control over possible representations. E.g.

module color
  private case rgb(data)
  type t = rgb(data)                   // "type t = rgb" is permitted as notational abbreviation

  private def clamp =
    (x -> if (x < 0) 0 else if (x > 255) 255 else x)

  def create : number -> number -> number -> t
  def create =
    ((r,g,b) -> rgb([clamp(r), clamp(g), clamp(b)]))

  def red : t -> number
  def red(col) = col |> rgb^ |> (triple -> triple[0])

  def green : t -> number
  def green(col) = col |> rgb^ |> (triple -> triple[1])

  def blue : t -> number
  def blue(col) = col |> rgb^ |> (triple -> triple[2])

  def add : t -> t -> t
  def add =
    ((col1, col2) ->
      create(red(col1)+red(col2), green(col1)+green(col2), blue(col1)+blue(col2))
    )
module end

It is still allowed to access the inner value of private cases. In particular, the deconstructor color.rgb^ is callable, and you can also pattern-match from outside the module.

Compatibility with data

Any parameterless case, and any case with a parameter that is a subtype of data is also considered as a subtype of data:

This means that you can treat such cases as data:

cell mycol : data = color.create(12,45,198)

You can get the original type back with a type assertion:

cell realcol : color.t = mycol |> type(color.t)

Unions