Skip to content

Type system: enum / union type design #116

@tmteam

Description

@tmteam

Enum / union type — design

Need a type for a fixed set of values. Three candidates with different semantics.


Candidate 1: C#-like enum (named constants)

Enum = set of named constants. By default — standalone type. With explicit base type — alias for constants of that type.

# Standalone type (from some)
type color = | red | green | blue

c = color.red
print(c)                 # 'red'
c == color.green         # false

# With base type — alias for int
type httpStatus: int = | ok = 200 | notFound = 404 | error = 500

s = httpStatus.ok        # 200 : httpStatus (= int)
s + 1                    # 201 : int (arithmetic works)

# With base type text
type direction: text = | north = 'N' | south = 'S' | east = 'E' | west = 'W'

Properties:

  • Enum value == value of base type (or unique singleton)
  • `==` works
  • Exhaustive when: compiler checks completeness
  • Without base type: `color.red != 0`, `color.red != 'red'` — separate type

Candidate 2: Tagged union (sum type)

Each variant can carry data. Like Rust enum, Haskell ADT.

type shape
    | circle(radius: real)
    | rect(width: real, height: real)
    | point

area = when s of shape:
    circle(r): pi * r * r
    rect(w, h): w * h
    point: 0

Properties:

  • Each variant is a constructor with optional fields
  • Pattern matching with destructuring
  • Exhaustive when
  • Significantly more complex in TIC (variant types, pattern destructuring)

Candidate 3: Sealed struct hierarchy

Combination of struct + type constraint. No new syntax needed.

type shape = { kind: text }

circle(r) = { kind = 'circle', radius = r }
rect(w, h) = { kind = 'rect', width = w, height = h }

area = when s.kind:
    'circle': pi * s.radius * s.radius
    'rect': s.width * s.height

Properties:

  • No new type in TIC needed
  • Pattern matching by field value
  • No exhaustive check (kind = any text)
  • No type safety — typo in kind not caught

Comparison

Property C#-like enum Tagged union Sealed struct
Data in variant no yes yes (via fields)
Exhaustive when yes yes no
TIC complexity low high zero
Pattern destructuring no yes no
Subtypes base type no row polymorphism
Implementation medium complex already works

Questions

  1. Is tagged union needed or is C#-like enum sufficient?
  2. If tagged union — how does it fit TIC? New StateVariant?
  3. Can we start with enum (simple), add union later?
  4. `|` — does it conflict with bitwise OR? (currently `|||` for bitwise)
  5. Is `of type` syntax in when needed for exhaustive check?

Metadata

Metadata

Assignees

No one assigned

    Labels

    NfunLanguageNFun-Lang full language modeSyntaxSyntactic and semantic improvements and sugarsWhat if?[Candidate]

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions