kind

A kind is a compositional descriptor that classifies values, defines their

structure, and constrains operations without a separate meta-type system.

Kinds describe the type, structure, and properties of values in Mech. Every value has one or more associated kinds, and kinds themselves are values that participate directly in the language.

Kinds contain information to describe:

  • Data type e.g. i32, string, bool, ec.

  • Data structure e.g. matrix, set, record, table or tuple

  • Data size e.g. matrix dimensions, set size, table rows

Kinds do not indicate whether a value is mutable or immutable. The mutability is determined by the user when the value is created, and is independent of its kind.

Syntax

Kinds are written using kind annotations, which enclose

a kind in angle brackets:

<i32>--

signed 32-bit integer

<string>--

string

<[u8]>--

matrix of u8 values

<(u8,bool)>--

tuple of u8 and bool

Each data structure has a unique syntax, see ( §4 ).

Kinds as Values

Kinds are values in Mech.

This means:

  • Kinds can be assigned to variables

  • Kinds can be passed, stored, and inspected

  • Kinds themselves have kinds

For example:

x:=<u8>

The value of x is <u8>, and the kind of x is <<u8>>.

This means the kind of <<u8>> is <<<u8>>>, and so on.

Simple Kinds

Simple kinds correspond directly to primitive data types.

Data Type

Kind

Signed integers

<i8>, <i16>, <i32>, <i64>, <i128>

Unsigned integers

<u8>, <u16>, <u32>, <u64>, <u128>

Floating-point

<f32>, <f64>

Rational

<r64>

Complex

<c64>

String

<string>

Boolean

<bool>

Atom

<:atom>

Kind

<kind>

Empty

<_>

Compound Kinds

Kinds compose structurally according to the data structures they describe.

Data Structure

Kind Syntax

Example

Meaning

Matrix

[T]:N,M

<[u8]:2,3>

2x3 matrix of u8 values

Set

{T}:N

<{u8}:3>

Set of 3 u8 values

Record

{field,...}

<{x<u8>,y<string>}>

Record with fields x and y

Map

{K:V}

<{string:i32}>

Map from string to i32

Table

|name,...|:N

<|x<u8>,y<string>|:3>

Table with columns x,y and 3 rows

Tuple

(T1,T2,...)

<(u8,string,bool)>

Ordered tuple of heterogeneous values

Compound kinds are recursively derived from the kinds of their constituent elements.

Kind Annotations

Kind annotations may be used in expressions to specify or constrain the kind of a value.

Literals

x:=42<u8>

Defines x as an unsigned 8-bit integer with value 42.

Variables

y<u8>:=10

Constrains y to always have kind <u8>.

Conversions

x:=[
1
2
3
]
--

[f64]:1,3

z<[u8]>:=x--

converts [f64]:1,3 -> [u8]:1,3

Conversions succeed only when a valid transformation exists, otherwise a compile-time error is raised.

Matrix Reshaping

m:=[
1
2
3
4
5
6
]
--

[f64]:1,6

n<[i32]:2,3>:=m--

reshapes to [i32]:2,3

Matrices may be reshaped to compatible dimensions using kind annotations.

Kind Membership (∈, ∉)

The set membership operators are also defined for kinds:

  • value ∈ returns true when value conforms to

  • value ∉ returns true when value does not conform to

Examples:

42<u64>--

true

42<string>--

true

This also applies to enum kinds (including payload variants):

<color>:=:red<u64>|:green<u64>|:blue:red(300)<color>--

true

:red("300")<color>--

false

Custom Kinds

Users may define custom kinds as aliases of existing kinds:

<T>:=<S>

Example:

<point3>:=<[f64]:3>

Usage:

p1<point3>:=[
1
2
3
]
p2<point3>:=[
4
5
]
--

Error: expected 3 elements

Custom kinds introduce semantic meaning without changing runtime representation.

Enumerations

Enumerations (enums) define a fixed set of named variants.

<color>:=:red|:green|:blue

The kind of the enum is , and The possible values are:

  • :red

  • :green

  • :blue

Example:

example<color>:=:green

Invalid variants are rejected:

example2<color>:=:yellow--

Error, yellow not in enum

Enums are kinds and participate in all kind-based reasoning. Enum variants are atoms, which are globally unique, immutable symbols, so namespace collisions are possible if another module defines the same variant name. To avoid this, you can use qualified names:

<color>:=:red|:green|:blueexample<color>:=:color/red

Which means the same thing as :red, but is guaranteed to be unique even if another module defines :red as well.

Variants with payload kinds

Enum variants may optionally carry data. Payload kinds can be written either inline (ok) or with parentheses (ok()):

<response>:=:ok<u64>|:error<string>|:timeoutr1<response>:=:ok(200)r2<response>:=:error("Not Found")r3<response>:=:timeout

In this enum:

  • ok requires a u64 payload

  • error requires a string payload

  • timeout carries no payload

Assignments with the wrong payload kind are rejected:

rbad<response>:=:ok("200")--

Error: expected u64 payload

Enum kinds in pattern matching

Enums participate in pattern matching like other kinds, including payload destructuring:

<response>:=:ok<u64>|:error<string>|:timeoutr<response>:=:error("Not Found")status-code<u64>:=r?
:ok(code) code
:error(msg) 500
:timeout 408
* 500.

When matching enum kinds, arms should be exhaustive (cover every variant or use *). Non-exhaustive matches are reported as compile-time errors.