kex docs Standard Library

Type

record Type

Types as values.

Type.of(x) answers what a value IS, as something you can hold, print, compare, and take apart:

Type.of(42)                     # Type { name: "Integer", args: [] }
Type.of([1, 2]).toString        # "[Integer]"
Type.of(x) == Type.of(y)        # structural equality, like any record
Type.of(due).fields             # ["year", "month", "day"]

The answer comes from the compiler where it can: a checked expression knows things a value cannot carry, such as the unused half of a Result or the element type of an empty list. Where the checker has no concrete answer — gradual code, --no-check, a value arriving from another process — the value itself is asked instead. That fallback is honest but lossy: an empty list has no element to inspect, and a Result only ever holds one side.

Fields

name
String
args
[Type]
pure
Bool

Methods

Everything else is a METHOD, not a module function: a module function is only reachable through UFCS in the interpreter, so Type.of(x).fields worked there and raised on BEAM.

fields

fields : [String]

Returns a record type's field names, in declaration order. Anything that is not a record answers with an empty list.

Reads the layout the compiler already ships to the runtime for display; there is no separate metadata to keep in step.

Returns the field names, or []

Examples
Type.of(Point { x: 1, y: 2 }).fields   # => ["x", "y"]
Type.of(42).fields                     # => []

Rendering a record generically

Type.of(value).fields.map { |name| "${name}: ..." }.join(", ")

constructors

constructors : [String]

Returns an ADT's constructor names. Anything that is not an ADT answers with an empty list.

Returns the constructor names, or []

Examples
Type.of(Circle(1)).constructors   # => ["Circle", "Square"]
Type.of(42).constructors          # => []

Listing what a sum type can be

IO.printLine("one of: ${Type.of(shape).constructors.join(", ")}")

record?

record? : Bool

Returns true when the type is a record — that is, when it has fields.

Returns true for a record type

Examples
Type.of(Point { x: 1, y: 2 }).record?   # => true
Type.of(42).record?                     # => false

adt?

adt? : Bool

Returns true when the type is a sum type — that is, when it has constructors.

Returns true for an ADT

Examples
Type.of(Circle(1)).adt?   # => true
Type.of(42).adt?          # => false

toString

toString : String

Renders the type the way it is written in SOURCE, not the way it is stored.

A list reads as [Integer], a tuple as (Integer, String), an optional as String?, a map as {String: Integer}, and a function as its signature.

Returns the type, as source

Examples
Type.of([1, 2]).toString      # => "[Integer]"
Type.of((1, "a")).toString    # => "(Integer, String)"
Type.of(Just(1)).toString     # => "Integer?"
Type.of("hi").toString        # => "String"

An error message that names the type

die("cannot serialise a ${Type.of(value).toString}")

module Type

Building and obtaining Type values.

of

of(value: Any) -> Type

Returns the type of value.

The entry point to everything else here. Prefer it over matching on the Type record directly.

Parameters
value
the value to inspect

Returns its type

Examples
Type.of(42)                # => Type { name: "Integer", args: [] }
Type.of([1, 2]).toString   # => "[Integer]"
Type.of("hi").toString     # => "String"

Reporting an unexpected value

IO.printError("expected a list, got ${Type.of(value).toString}")

named

named(name: String) -> Type

Builds a type from its name, for comparing against something you already know.

Parameters
name
the type name

Returns the named type

Examples
Type.of(42) == Type.named("Integer")   # => true

Checking that a value came back as expected

Type.of(parsed) == Type.named("Date")

generic

generic(name: String, args: [Type]) -> Type

Builds a type that takes arguments, from its name and those arguments.

Renamed from Type.with when with became the capability-substitution keyword (kexhq/kex#143).

Parameters
name
the type name
args
its type arguments

Returns the generic type

Examples
Type.of([1]) == Type.generic("List", [Type.named("Integer")])   # => true

function

function(params: [Type], result: Type) -> Type

Builds a function type from its parameter types and its result type — in the order a signature is written.

Parameters
params
the parameter types
result
the result type

Returns the function type

Examples
Type.function([Type.named("String")], Type.named("String")).toString
# => "String -> String"

returnedBy

returnedBy(function: Any) -> Type

Returns the type a named function returns, as answered by the compiler.

Named functions only. A lambda or a function VALUE carries no signature at runtime, and an overloaded name has no single answer — both are compile errors rather than a guess.

Parameters
function
a named function

Returns its return type

Examples
Type.returnedBy(Date.parse).toString   # => "Result<Date, TimeError>"