hanki
Hanki is a statically typed language with exact arithmetic, checked effects and isolated actors. Develop interactively in the live REPL, run source with the bytecode interpreter, or compile native programs with LLVM.
Exact arithmetic
Decimal literals are exact, ordinary integers have arbitrary precision, and division preserves fractions.
0.1 + 0.2
1 / 3
(1 / 3) * 3
These expressions produce 0.3, one third and 1. No decimal or fraction wrapper is required. Floating-point types are available when approximate arithmetic is appropriate.
The library includes calendar dates, durations and periods, alongside JSON, HTTP and SQLite.
Checked effects
Pure functions calculate values. Actions declare effects such as I/O, and the checker verifies those declarations through calls. Adding I/O to a pure calculation requires a change to its contract.
# The smallest program that shows both layers: a pure function and an action.
use io
def greet(name: string) -> string
"Hello, #{name}\n"
end
def main!() -> () [io]
io.print!(greet("world"))
end
The ! suffix identifies an action; [io] declares its I/O effect. hanki effects reports a program’s effects before execution. Type-and-effect holes report the expected type and permitted effects while an implementation is incomplete.
Live development
The REPL checks types and effects with the same front end as source files. Bindings and actors persist between inputs. After defining a counter actor, successive messages operate on the same state:
c = spawn Counter
c.increment()
c.get()
= 1
c.increment()
c.get()
= 2
Documentation, type queries and source reload are available at the prompt. See the REPL reference for the complete Counter definition.
Scripts and native programs
One language covers both roles. hanki run executes source on the bytecode interpreter with no build step, and a file that begins with #!/usr/bin/env -S hanki run runs as a script. hanki build compiles the same source with LLVM into a native executable.
hanki run report.hk # bytecode interpreter, no build step
hanki build app.hk # native executable at out/app
A program must have the same output, errors, effects and exit code on both tiers; only time and memory differ. The differential tests run the example programs on both tiers and compare the results, and hanki test --tier both runs a project's tests on each.
Hanki's own development tools are Hanki programs run with hanki run, among them the prose linter and the generator that built this site. A project's scripts and its application are written in one language and checked by one compiler.
Isolated actors
Actors have private state and heaps, typed messages, bounded mailboxes and supervision. Message passing separates concurrent work without shared mutable values.
Run actor tests with hanki test PATH --seed 7 to select a repeatable schedule. Repeating the command with the same program and inputs reproduces that schedule. External responses are inputs to supply again; the seed does not record them.
Actors currently use OS threads. Seeded testing explores schedules without proving that every possible interleaving is correct.
Automatic memory management
Per-actor reference counts reclaim values when their last handle drops. Resource handles release native state at the same boundary, and explicit close operations are available for earlier release.
Ordinary code needs no lifetime annotations or allocator plumbing. The value model is acyclic: graphs use identifiers or actor references. There is no tracing or cycle collector; reclamation still takes work and has no hard real-time guarantee.
Status
spec-first. Most of what follows describes the target design. Section 22 tracks what is implemented.
The source is not public yet, and Hanki has no public release.
The whole tree is 0BSD (what that means for your programs).