WokML

Wok

Frontier control flow. Deterministic by construction.

Wok is a small ML-family language where the compiler erases reference counts at compile time, so pure functions mutate in place. Lifetimes are traced by one-shot continuations; effects are handled, not stacked. A glue language — not a replacement for your general-purpose stack.

Read the docs

Built for mission critical applications.

Small by design, designed for easy integration
We have designed Wok to work great alongside your C stack. Wok serves the control flow logic, with verified model and specialised design runtime.
The Wok reclamation model
No garbage collector. The compiler tracks every value’s lifetime itself — so when you transform data you uniquely own, the old cell becomes the new cell, in place. No allocation, no churn.
One-shot continuations
An effect handler can pause the program, step aside, then resume from where it left off. In wok, that resume happens at most once — enforced at compile time. That guarantee lets the compiler track every value’s lifetime for you — no lifetime annotations, no manual borrowing.
No value restriction
Because a continuation resumes at most once, it can’t re-observe captured state at a different type. The unsoundness that forces ML languages to restrict polymorphic values never arises — so Wok drops the value restriction entirely.
Algebraic effect handlers
Write orthogonal effects without monad transformers. Composable, and natural to read.
Relational fixity
Operator precedence is relational, not numeric — you declare fixity * left tighter than + instead of memorizing a precedence table. Ordering stays readable as the language grows.

The Wok discipline, in code.

The Wok reclamation model

-- Each Cons shell from the input spine is reused in place to build
-- the accumulator. Net spine allocation: zero.
data List = Nil | Cons U64 List

rev : List -> List -> List
rev acc xs = case xs of
  Nil       -> acc
  Cons x xx -> rev (Cons x acc) xx

main = rev Nil (Cons 1 (Cons 2 (Cons 3 Nil)))

A pure transform. Each consumed cell is reborn as its successor — no GC, no allocation.

Algebraic effect handlers

-- The State effect and its runner. The handler threads state through
-- every get/set; the value arm returns (result, finalState).
effect State s = { get : s, set : s -> () }
state : s -> (() -> a with State s + eff e) -> (a, s) with eff e
state i c = with State { s = i ; get -> s ; set x k -> k x () ; v -> (v, s) } c ()

-- Using it: state is threaded implicitly, no explicit parameter.
main : (U64, U64)
main =
  with state 100 in
  let a = State.get in
  let b = State.set (a + 5) in
  State.get

State, exceptions, readers, generators — all one mechanism. No monad transformers.

JIT FFI to C

foreign module Libc "c" free "free" where
  owned strndup : Bytes -> U64 -> Bytes with IO

-- Calls libc's strndup directly. The `owned` marker hands Wok full
-- lifetime control of the returned buffer; Wok frees it at rc 0.
main = Libc.strndup (fromList [1, 2, 3, 4]) 2

Real C calls, with explicit borrowership at the boundary. Wok owns what owned returns.

Get wokup.

We host a version manager for the compiler suite — one line to install.

$ curl -fsSL wokml.org/up | sh  # coming soon

Experimental v0.1

Wok is experimental (v0.1) — the syntax and semantics are still settling, so expect changes. What works today: a working compiler with type inference, effect handlers, compile-time memory management, and a direct C interop layer — all verified by an automated test harness that runs every program twice and checks the results match exactly.

On the road: a richer C integration so Wok can hand memory to and receive it from external libraries safely; arrays that live directly in C for predictable performance; and the long-term goal of bootstrapping — writing the Wok compiler in Wok itself.