Algebraic effects
What a function does is written in its type, and you decide how it is resolved with a handler. No more async/await spreading through the whole call stack.
fn greet(name: String) : Unit / Log {
Log.log("hello, #{name}")
} A functional language with algebraic effects and isolated fibers. No garbage collector, no borrow checker.
curl -fsSL https://raw.githubusercontent.com/kaikailang-org/kaikai/main/install.sh | sh effect Log {
log(msg: String) : Unit
}
fn greet(name: String) : Unit / Log {
Log.log("hello, #{name}")
}
fn main() {
handle {
greet("kaikai")
greet("world")
} with Log {
log(msg, resume) -> {
println("[INFO] #{msg}")
resume(())
}
}
}$ kai run effect.kai[INFO] hello, kaikai
[INFO] hello, world Agents first
A new language has no millions of programs for a model to learn from. kaikai bets on another path: the compiler answers with precise data, and the agent iterates until it reaches the right program.
1You write the signature
fn passed(grades: [(String, Int)]) : [String] = ?body 2The compiler answers
$ kai build --holes-json{
"name": "body",
"expected_type": "[String]",
"in_scope": [
{"name": "grades", "type": "[(String, Int)]"}
],
"candidates": [
{"expr": "[]", "kind": "literal"}
]
} 3The agent fills it in
fn passed(grades: [(String, Int)]) : [String] =
grades
|? . .1 >= 4
| . .0
|> list.sort kai build --holes-json What type each hole expects, what is in scope and which candidates fit. kai build --diags-json Errors with file, line and message, ready to process. kai build --effects-json The effects of every function. Knowing whether it touches the disk takes no code reading. kai check --json The result of every test, and the exact counterexample when a property fails. kai info llm The bootstrap guide for an agent arriving at a kaikai repository. kai info <topic> --json The language documentation as data, without opening a browser. This site also introduces itself to models in llms.txt, and chapter 15 of the book tells the whole workflow.
Six ideas that define the language, each with the code that shows it.
What a function does is written in its type, and you decide how it is resolved with a handler. No more async/await spreading through the whole call stack.
fn greet(name: String) : Unit / Log {
Log.log("hello, #{name}")
} Four operators, four intents: |> applies, | maps, || flat-maps and |? filters. You know what each step does before you read the function.
let total = [1..4]
| square
|| divisors
|? is_even
|> list.sum Perceus reference counting and isolated fibers. Each fiber looks after its own memory, so there are no global pauses and no borrow checker to argue with.
let f = spawn.spawn { worker("B", 3) }
worker("A", 3)
spawn.await(f) Real<m/s> for measures, currencies that never mix, and memory regions with region { }. The information lives in the type and costs nothing at run time.
fn to_usd(amount: Real<EUR>, rate: Real<USD/EUR>) : Real<USD>
= amount * rate requires, ensures and Int where >= 0. What a function demands and what it promises sit right next to it, in the spirit of SPARK and without an SMT solver.
fn divide(a: Int, b: Int) : Int
requires b != 0
ensures result * b == a
{
a / b
} Leave a hole with ? and the compiler tells you what type it expects there, in JSON too. Designed for people and agents to write together.
fn circle_area(r: Real) : Real = ?formula $ kai build --holes-json"expected_type": "Real" A whole program and what it prints. It takes the numbers 1 to 4 and chains all four pipes to sum the even squares.
See all nine examplesfn square(n: Int) : Int = n * n
fn divisors(n: Int) : [Int] = [1, n]
fn is_even(n: Int) : Bool = n % 2 == 0
fn main() {
# `[1..4]` is a range literal: no hand-written accumulator loop.
# `[1..10..2]` adds a step.
let total = [1..4] # [1, 2, 3, 4]
| square # [1, 4, 9, 16] (map)
|| divisors # [1, 1, 1, 4, 1, 9, 1, 16] (flat-map)
|? is_even # [4, 16] (filter)
|> list.sum # 20 (apply)
println("total=#{total}")
}$ kai run 06_pipes.kaitotal=20 It installs with a single command on macOS, Linux and Windows (via WSL2), with no dependencies. And the book walks with you from the first program to a complete case study.
curl -fsSL https://raw.githubusercontent.com/kaikailang-org/kaikai/main/install.sh | sh