Skip to main content

AILANG Examples

Learn AILANG through interactive examples. Each example demonstrates a key feature with real working code from the repository.

Quick Start Examples​

Hello World​

The simplest AILANG program with I/O effects:

examples/runnable/hello.ail
-- hello.ail - Simple hello world program
module examples/runnable/hello
import std/io (print)

-- Entry module with exported main function
export func main() -> () ! {IO} = print("Hello, AILANG!")
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/hello.ail

Key concepts:

  • ! {IO} declares the function performs I/O
  • println is imported from std/io
  • --caps IO grants I/O capability at runtime

Recursion & Pure Functions​

AILANG uses recursion instead of loops for deterministic control flow:

examples/runnable/recursion_factorial.ail
-- recursion_factorial.ail
-- Demonstrates simple recursive function with LetRec
-- Status: ✅ Working (M-R4 recursion support)

module examples/runnable/recursion_factorial
import std/io (println)

-- Classic factorial using recursion
pure func factorial(n: int) -> int
tests [
(0, 1),
(1, 1),
(5, 120),
(10, 3628800),
(12, 479001600)
] {
if n <= 1 then 1 else n * factorial(n - 1)
}

-- Tail-recursive factorial with accumulator
pure func factorialTail(n: int, acc: int) -> int
tests [
((0, 1), 1),
((1, 1), 1),
((5, 1), 120),
((10, 1), 3628800),
((12, 1), 479001600)
] {
if n <= 1 then acc else factorialTail(n - 1, n * acc)
}

export func main() -> () ! {IO} {
let result1 = factorial(5)
let result2 = factorialTail(10, 1)
println("factorial(5) = ${show(result1)}")
println("factorialTail(10, 1) = ${show(result2)}")
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/recursion_factorial.ail

Note: The main function is the default entrypoint. This example prints factorial results using IO.

Key concepts:

  • factorial is pure (no effects declared)
  • Recursion replaces loops for deterministic reasoning
  • show() converts int to string for printing

Pattern Matching​

Lists & Destructuring​

Pattern matching is AILANG's primary control flow mechanism:

examples/runnable/list_sum.ail
-- list_sum.ail - List operations with pattern matching
-- Demonstrates ADT destructuring and recursion

type IntList = INil | ICons(int, IntList)

-- Sum all integers in a list using letrec for recursion
letrec sum = \list. match list {
INil => 0,
ICons(head, tail) => head + sum(tail)
} in letrec length = \list. match list {
INil => 0,
ICons(_, tail) => 1 + length(tail)
} in let numbers = ICons(1, ICons(2, ICons(3, ICons(4, ICons(5, INil))))) in (sum(numbers), length(numbers))
View source on GitHub

Run it:

ailang run examples/runnable/list_sum.ail

Output:

(15, 5)

Key concepts:

  • INil matches empty list
  • ICons(head, tail) destructures list
  • letrec enables recursive function definitions
  • Exhaustive matching required (compiler enforces)

Algebraic Data Types (ADTs)​

Define custom types with multiple constructors:

examples/runnable/adt_tree.ail
-- adt_tree.ail - Binary tree ADT with sum operation
-- Demonstrates recursive ADTs and pattern matching
module examples/runnable/adt_tree

type Tree = Leaf(int) | Node(Tree, int, Tree)

-- Sum all values in a tree (recursive pattern matching)
pure func sumTree(tree: Tree) -> int = match tree {
Leaf(n) => n,
Node(left, value, right) => sumTree(left) + value + sumTree(right)
}

-- Count nodes in tree
pure func countNodes(tree: Tree) -> int = match tree {
Leaf(_) => 1,
Node(left, _, right) => 1 + countNodes(left) + countNodes(right)
}

export func main() -> () ! {IO} =
let tree = Node(Leaf(1), 2, Node(Leaf(3), 4, Leaf(5))) in
let _ = println("Tree sum: ${show(sumTree(tree))}") in
println("Node count: ${show(countNodes(tree))}")
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/adt_tree.ail

Output:

Tree sum: 15
Node count: 5

Key concepts:

  • type Tree = defines an ADT with 2 constructors
  • pure func declares functions without side effects
  • Pattern matching handles all cases
  • Compiler ensures exhaustiveness

Effect System​

Multiple Effects​

Functions can declare multiple effects they perform:

examples/runnable/effects_fs_io.ail
-- effects_fs_io.ail - Demonstrates multiple effect capabilities
-- Shows combining IO and FS effects in a single function
module examples/runnable/effects_fs_io
import std/io (println)
import std/fs (fileExists, readFile, writeFile)

-- Function that combines IO and FS effects
-- Note: ! {IO, FS} declares both capabilities
export func main() -> () ! {IO, FS} {
let path = "/tmp/ailang_test.txt"
let content = "Hello from AILANG!"
-- Write a test file (FS effect)
writeFile(path, content)
-- Print confirmation (IO effect)
println("Wrote: ${content}")
-- Check if file exists (FS effect)
let fileOk = fileExists(path)
println("File exists: ${show(fileOk)}")
-- Read it back (FS effect)
let readBack = readFile(path)
println("Read back: ${readBack}")
}
View source on GitHub

Run it:

ailang run --caps IO,FS examples/runnable/effects_fs_io.ail

Key concepts:

  • ! {IO, FS} declares both I/O and filesystem effects
  • Sequential statements use ; in block expressions
  • Import functions from stdlib modules

Effect Polymorphism​

Functions can be generic over effects. This allows writing reusable code that works with any combination of capabilities:

-- Effect row polymorphism: {IO | e} means "IO plus any other effects"
-- This allows functions to compose while preserving effect safety

Key concepts:

  • Effect rows can be extended with {IO | e} syntax
  • Effect polymorphism enables reusable library functions
  • Effects compose naturally when calling functions

Type System​

Type Inference​

AILANG infers types automatically using Hindley-Milner:

examples/runnable/type_inference.ail
-- Showcase: Type Inference
-- The type checker automatically infers types!
module examples/runnable/type_inference

export func main() -> () ! {IO} =
let double = \x. x * 2 in
let result = double(21) in
println("Type inference: ${show(result)}")
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/type_inference.ail

Key concepts:

  • Type inference works across function boundaries
  • Explicit annotations optional but recommended
  • :type command in REPL shows inferred types

Records & Subsumption​

Records are structural types with width subtyping:

examples/runnable/records.ail
-- records.ail - Record examples
-- Demonstrates record literals, field access, and nested records

-- =======================
-- BASIC RECORDS
-- =======================

-- Simple record literal
{name: "Alice", age: 30}
-- Output: {name: "Alice", age: 30}

-- Record with multiple types
{id: 1, name: "Bob", active: true, score: 98.5}
-- Output: {id: 1, name: "Bob", active: true, score: 98.5}

-- =======================
-- FIELD ACCESS
-- =======================

-- Single field access
let person = {name: "Charlie", age: 25} in
person.name
-- Output: "Charlie"

-- Multiple field access
let user = {id: 123, email: "test@example.com"} in
"${show(user.id)} - ${user.email}"
-- Output: "123 - test@example.com"

-- =======================
-- NESTED RECORDS
-- =======================

-- Record with nested structure
let company = {
name: "Acme Corp",
ceo: {
name: "Jane Doe",
age: 45
}
} in
company.ceo.name
-- Output: "Jane Doe"

-- Deeper nesting
let data = {
user: {
profile: {
name: "Deep",
email: "deep@test.com"
}
}
} in
data.user.profile.email
-- Output: "deep@test.com"

-- =======================
-- RECORDS IN EXPRESSIONS
-- =======================

-- Record with computed fields
let x = 10 in
let y = 20 in
{sum: x + y, product: x * y, x: x, y: y}
-- Output: {sum: 30, product: 200, x: 10, y: 20}

-- Using record fields in calculations
let rect = {width: 5, height: 10} in
rect.width * rect.height
-- Output: 50

-- =======================
-- RECORDS WITH FUNCTIONS
-- =======================

-- Record containing lambda functions
let math = {
add: \x y. x + y,
multiply: \x y. x * y,
square: \x. x * x
} in
math.square(5)
-- Output: 25

-- Using functions from records
let ops = {
double: \x. x * 2,
triple: \x. x * 3
} in
ops.double(21)
-- Output: 42

-- =======================
-- PATTERN MATCHING
-- =======================

-- Record patterns (v0.6.2+)
-- See examples/runnable/record_patterns.ail for comprehensive examples
let person = {name: "Alice", age: 30} in
match person {
{name, age} => "${name} is ${show(age)}"
}
-- Output: "Alice is 30"

-- =======================
-- COMPLEX EXAMPLES
-- =======================

-- Record with mixed types and nesting
let config = {
app: {
name: "MyApp",
version: "1.0.0"
},
server: {
host: "localhost",
port: 8080,
ssl: false
},
features: {
debug: true,
logging: true
}
} in
"${config.app.name} v${config.app.version}"
-- Output: "MyApp v1.0.0"

-- Building a result from record fields
let point = {x: 3, y: 4} in
let distance = \p.
let dx = p.x * p.x in
let dy = p.y * p.y in
dx + dy -- Would be sqrt(dx + dy) with math functions
in
distance(point)
-- Output: 25
View source on GitHub

Run it:

ailang run examples/runnable/records.ail

Key concepts:

  • Records support structural typing
  • Width subtyping: {a, b, c} ⊆ {a, b}
  • Field access: record.field
  • Nested records and lambda fields supported

Int Literals at Float Type​

A numeric literal such as 0 or 2 takes the type it is used at. So f >= 0, 2 * f, a float function that returns 0, and make(3, 0) for an Array[float] all produce floats:

examples/runnable/float_int_literals.ail
-- Int literals used as floats: a numeric literal like 0 or 2 takes the type it
-- is used at, so `f >= 0`, `2 * f`, `-> float { 0 }`, `[1, f, 3]` and
-- `make(3, 0)` for an Array[float] are all float values (0.0, 2.0, ...).
-- A let-bound int literal picks ONE numeric type from its uses; mixing int and
-- float for the same binding is a type error, so annotate it or use intToFloat.
module examples/runnable/float_int_literals
import std/array (make, scatterAdd)
import std/math (intToFloat)

pure func isNonNeg(f: float) -> bool = f >= 0

pure func double(f: float) -> float = 2 * f

pure func zero() -> float = 0

pure func around(f: float) -> [float] = [1, f, 3]

-- Histogram on an Array[float]: the 0 and the 1, 2, 5 literals are floats.
pure func histogram() -> Array[float] = scatterAdd(make(3, 0), [0, 0, 2], [1, 2, 5])

-- `w` is used in a float division, so the int literal 70 is the float 70.0.
pure func bmi(h: float) -> float {
let w = 70
w / (h * h)
}

-- An annotated int stays an int; convert explicitly when mixing int and float.
pure func average(total: float) -> float {
let n: int = 4
total / intToFloat(n)
}

export func main() -> () ! {IO} {
println("isNonNeg(2.5) = ${show(isNonNeg(2.5))}")
println("double(1.5) = ${show(double(1.5))}")
println("zero() = ${show(zero())}")
println("around(2.5) = ${show(around(2.5))}")
println("histogram = ${show(histogram())}")
println("bmi(2.0) = ${show(bmi(2.0))}")
println("average(10.0) = ${show(average(10.0))}")
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/float_int_literals.ail

Key concepts:

  • An int literal used at type float is a float value (0 → 0.0)
  • A let-bound numeric literal picks ONE type from its uses
  • Mixing int and float for the same binding is a type error: annotate the binding (let n: int = 4) and convert with intToFloat
  • Literal syntax: Language Syntax reference

JSON & HTTP​

JSON Parsing​

Parse and work with JSON data:

examples/runnable/json_parsing.ail
-- json_parsing.ail - JSON parsing example
-- Demonstrates JSON decode with convenience functions (v0.6.4+)
module examples/runnable/json_parsing
import std/io (println)
import std/json (decode, getString, getNumber)
import std/result (Result, Ok, Err)
import std/option (Option, Some, None)

-- Parse JSON and extract values using convenience functions
export func main() -> () ! {IO} {
let jsonStr = "{\"name\": \"AILANG\", \"version\": 0.6}"
match decode(jsonStr) {
Ok(obj) => {
println("Parsed JSON successfully!")
-- Extract name field using getString (combines get + asString)
match getString(obj, "name") {
Some(name) => println("Name: ${name}"),
None => println("Name not found or not a string")
}
-- Extract version using getNumber
match getNumber(obj, "version") {
Some(ver) => println("Version: ${show(ver)}"),
None => println("Version not found or not a number")
}
},
Err(e) => println("Parse error: ${e}")
}
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/json_parsing.ail

Key concepts:

  • decode returns Result[Json, string]
  • Pattern match on JSON structure using Ok/Err
  • Use get and asString helpers for field access

HTTP Requests​

Make HTTP requests with the Net effect:

examples/runnable/http_simple.ail
-- http_simple.ail - Simple HTTP request example
-- Demonstrates Net effect for HTTP calls
module examples/runnable/http_simple
import std/io (println)
import std/net (httpGet)
import std/string (length)

-- Fetch a URL and print status
export func main() -> () ! {IO, Net} {
let url = "https://httpbin.org/get"
-- Simple GET request (returns body string)
println("Fetching: ${url}")
let response = httpGet(url)
println("Response length: ${show(length(response))} bytes")
}
View source on GitHub

Run it:

ailang run --caps IO,Net examples/runnable/http_simple.ail

Key concepts:

  • ! {IO, Net} declares network capability
  • httpGet returns response body as string
  • DNS rebinding protection built-in

Data Formats​

ZIP Archives​

Read and inspect ZIP archives (including .docx, .xlsx, .pptx files):

examples/runnable/zip_reader.ail
-- ZIP archive reading with std/zip
-- Demonstrates listing and reading entries from ZIP archives
-- Requires FS capability and a ZIP file to operate on
--
-- Usage: ailang run --caps IO,FS --entry main zip_reader.ail
module examples/runnable/zip_reader
import std/result (Result, Ok, Err)
import std/zip (listEntries, readEntry, readEntryBytes)

-- Example: inspect a .docx file (which is a ZIP archive)
-- .docx contains: word/document.xml, [Content_Types].xml, etc.
export func main() -> int ! {IO, FS} {
let path = "test.docx"
match listEntries(path) {
Ok(entries) => {
println("Archive entries:");
-- entries is a list of strings (entry paths)
0
},
Err(msg) => {
println(msg);
1
}
}
}
View source on GitHub

Run it:

ailang run --caps IO,FS examples/runnable/zip_reader.ail

Key concepts:

  • ! {FS} declares filesystem access for ZIP reading
  • _zip_listEntries lists all entries in the archive
  • _zip_readEntry reads text content (XML, JSON, etc.)
  • _zip_readEntryBytes reads binary content as base64

XML Parsing​

Parse and query XML documents (pure functions, no effects needed):

examples/runnable/xml_parser.ail
-- XML parsing with std/xml
-- Demonstrates parsing XML and querying the tree with findAll, getText, getAttr
--
-- Usage: ailang run --entry main xml_parser.ail
module examples/runnable/xml_parser
import std/result (Result, Ok, Err)
import std/xml (parse, findAll, findFirst, getText, getTag)

-- Parse XML and extract information using tree queries
export func main() -> int ! {IO} {
let xml = "<catalog><book id=\"1\"><title>AILANG Guide</title><author>Claude</author></book><book id=\"2\"><title>Functional Design</title><author>AI</author></book></catalog>"
match parse(xml) {
Ok(root) => {
-- Find all book elements
let books = findAll(root, "book")
println("Found books:")
-- Find first title element
match findFirst(root, "title") {
Some(titleNode) => {
let titleText = getText(titleNode)
println(titleText)
},
None => println("No title found")
}
-- Get tag name of root (returns string, empty for non-Element)
let tag = getTag(root)
println(tag);
0
},
Err(msg) => {
println(msg);
1
}
}
}
View source on GitHub

Run it:

ailang run examples/runnable/xml_parser.ail

Key concepts:

  • _xml_parse returns Result[XmlNode, string] - pure function
  • _xml_findAll and _xml_findFirst query by tag name
  • _xml_getText, _xml_getAttr extract content
  • XmlNode ADT: Element | Text | CData | Comment

Regular Expressions​

Match, find, capture, replace and split with std/regex, which uses the linear-time RE2 engine. See the standard library reference:

examples/runnable/regex_basics.ail
-- regex_basics.ail - std/regex regular expressions: match, find all, capture groups, replace, split.
-- Write regex escapes with a doubled backslash in AILANG strings: "\\d+" ("\d" is a parse error).
-- Import std/regex qualified (`as R`): its split clashes with std/string's split.
-- RE2 engine: linear time, no backreferences or lookaround; compile is the only fallible step.
module examples/runnable/regex_basics
import std/io (println)
import std/list (map)
import std/regex as R

export func main() -> () ! {IO} {
match R.compile("([a-z]+)=(\\d+)") {
Err(e) => println("bad pattern: ${e}"),
Ok(re) => {
-- isMatch: does the pattern occur anywhere?
println(show(R.isMatch(re, "x=1")))
println(show(R.isMatch(re, "no pairs here")))
-- findAll: every non-overlapping match, left to right
println(show(map(\m. m.text, R.findAll(re, "a=1, bb=22"))))
-- findFirst: groups holds the whole match first, then each capture group
match R.findFirst(re, "key=42") {
Some(m) => println(show(map(\g. g.text, m.groups))),
None => println("no match")
}
-- replaceAll: refer to capture groups as $1, $2
println(R.replaceAll(re, "a=1 b=2", "$2:$1"))
-- split: the text between matches
println(show(R.split(re, "x a=1 y")))
}
}
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/regex_basics.ail

Key concepts:

  • R.compile(pattern) returns a Result. It is the only call that can fail; matching cannot
  • Double the backslash in AILANG strings: "\\d+". Writing "\d" is a parse error
  • Import std/regex as R, because its split clashes with std/string's
  • findFirst returns groups: the whole match first, then each capture group. replaceAll refers to them as $1, $2

Testing & Verification​

Property-Based Differential Testing​

Check a fast algorithm against a slow, obviously-correct reference on generated inputs. ailang test runs each property on 100 generated cases and prints the failing input as a counterexample:

examples/runnable/property_differential_testing.ail
-- Property-based differential testing: check a fast algorithm against a slow,
-- obviously-correct reference on generated inputs, before trusting it.
-- `ailang test` runs each `property` on 100 generated cases and prints the
-- failing input as a counterexample (replay with --seed). Python's stdlib has no equivalent.
module examples/runnable/property_differential_testing

import std/list (foldl, length)
import std/io (println)

-- Brute force: the best sum over every non-empty contiguous slice. O(n^2), easy to trust.
func bestFrom(xs: [int], acc: int, best: int) -> int =
match xs {
[] => best,
x :: rest =>
let s = acc + x in
bestFrom(rest, s, if s > best then s else best)
}

func bruteMaxSlice(xs: [int]) -> int =
match xs {
[] => 0,
x :: rest =>
let here = bestFrom(rest, x, x) in
let later = bruteMaxSlice(rest) in
if length(rest) == 0 then here else if here > later then here else later
}

-- Fast: Kadane's algorithm, one pass. This is the version to submit.
export func maxSlice(xs: [int]) -> int =
match xs {
[] => 0,
x :: rest =>
let step = \st y.
match st { (cur, best) =>
let c = if cur + y > y then cur + y else y in
(c, if c > best then c else best) } in
match foldl(step, (x, x), rest) { (_, best) => best }
}

test "known case" { maxSlice([-2, 1, -3, 4, -1, 2, 1, -5, 4]) == 6 }

property "fast agrees with brute force" {
forall(xs: [int]) => maxSlice(xs) == bruteMaxSlice(xs)
}

export func main() -> () ! {IO} =
println("maxSlice = ${show(maxSlice([-2, 1, -3, 4, -1, 2, 1, -5, 4]))}")
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/property_differential_testing.ail
ailang test examples/runnable/property_differential_testing.ail

Key concepts:

  • forall(xs: [int]) => ... generates lists, ints and other inputs for you
  • A failing property prints its counterexample, replayable with ailang test --seed N
  • Write the brute-force reference first, then let the property check the fast version before you trust it

Collections: Sets, Structured Keys, Batch Updates​

The competitive-programming toolkit in pure AILANG: a visited set, tuple and record map keys, and a difference array. See the Stdlib Index for std/set, std/map and std/array.

Visited Set BFS​

Shortest path on a grid with a visited Set[(int, int)] and a list frontier:

examples/runnable/visited_set_bfs.ail
-- Visited set BFS: shortest path on a grid with std/set.
-- A Set[(int, int)] of visited cells plus a list frontier is the AILANG form of
-- Python's `visited = set()` + deque BFS. Name the type with `import std/set (Set)`.
module examples/runnable/visited_set_bfs
import std/io (println)
import std/set as S
import std/set (Set)
import std/array as A
import std/string (charAt, length as strLen)
import std/list (filter, flatMap, foldl, any)

func passable(g: Array[string], p: (int, int)) -> bool = match p {
(r, c) => r >= 0 && r < A.length(g) && c >= 0 && c < strLen(A.get(g, 0)) && charAt(A.get(g, r), c) == "."
}

func neighbours(g: Array[string], p: (int, int)) -> [(int, int)] = match p {
(r, c) => filter(\q. passable(g, q), [(r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)])
}

-- Add p to the next frontier only if it is not yet visited.
func visit(st: (Set[(int, int)], [(int, int)]), p: (int, int)) -> (Set[(int, int)], [(int, int)]) = match st {
(seen, next) => if S.member(seen, p) then st else (S.insert(seen, p), p :: next)
}

-- One BFS level per call; -1 when the frontier empties without reaching goal.
func bfs(g: Array[string], frontier: [(int, int)], seen: Set[(int, int)], goal: (int, int), dist: int) -> int =
if any(\p. p == goal, frontier) then dist else match foldl(visit, (seen, []), flatMap(\p. neighbours(g, p), frontier)) {
(_, []) => -1,
(seen2, next) => bfs(g, next, seen2, goal, dist + 1)
}

export func main() -> () ! {IO} {
let g = A.fromList(["..#....", ".##.##.", "....#..", "#.#...#", "...#..."])
println("shortest path (0,0) -> (4,6): ${show(bfs(g, [(0, 0)], S.fromList([(0, 0)]), (4, 6), 0))}")
println("goal is a wall: ${show(bfs(g, [(0, 3)], S.fromList([(0, 3)]), (0, 2), 0))}")
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/visited_set_bfs.ail

Key concepts:

  • import std/set as S for the functions, import std/set (Set) to write the type (S.Set[...] does not parse)
  • Set elements can be tuples, records and ADT constructors
  • S.member is O(1); S.insert copies the set (O(n)) until persistent maps land

Cycle Detection with a Visited Set​

Count moves until a (row, col, Dir) state repeats:

examples/runnable/cycle_detection_visited_set.ail
-- Cycle detection with a visited set of states: Set[(int, int, Dir)] from std/set.
-- A robot moves until it repeats a (row, col, direction) state, the way Python
-- does `if state in seen: break; seen.add(state)`. ADT constructors work in set keys.
module examples/runnable/cycle_detection_visited_set
import std/io (println)
import std/set as S
import std/set (Set)

type Dir = N | E | S | W

func turn(d: Dir) -> Dir = match d {
N => E,
E => S,
S => W,
W => N
}

func ahead(r: int, c: int, d: Dir) -> (int, int) = match d {
N => (r - 1, c),
E => (r, c + 1),
S => (r + 1, c),
W => (r, c - 1)
}

-- On a size x size grid with blocked cells, step forward or turn right; count
-- moves until the first repeated state.
func walk(size: int, blocked: Set[(int, int)], r: int, c: int, d: Dir, seen: Set[(int, int, Dir)], moves: int) -> int =
if S.member(seen, (r, c, d)) then moves else match ahead(r, c, d) {
(r2, c2) => if r2 < 0 || r2 >= size || c2 < 0 || c2 >= size || S.member(blocked, (r2, c2)) then walk(size, blocked, r, c, turn(d), S.insert(seen, (r, c, d)), moves + 1) else walk(size, blocked, r2, c2, d, S.insert(seen, (r, c, d)), moves + 1)
}

export func main() -> () ! {IO} {
let blocked = S.fromList([(0, 2), (2, 1)])
println("moves before a repeated state: ${show(walk(3, blocked, 0, 0, E, S.empty(), 0))}")
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/cycle_detection_visited_set.ail

Key concepts:

  • Set[(int, int, Dir)]: an ADT constructor inside a tuple element
  • The AILANG form of Python's if state in seen: break

Tuple and Record Map Keys​

Tuples, records and ADT constructors as std/map keys:

examples/runnable/map_tuple_record_keys.ail
-- Structured map keys: tuple keys, record keys and ADT keys in std/map (and std/set).
-- Grid coordinates (r, c) as a Map key, a record as a key (field order does not
-- matter), an ADT constructor as a key; keys iterate in a deterministic order.
module examples/runnable/map_tuple_record_keys
import std/io (println)
import std/map as M

type Color = Red | Green | Blue

export func main() -> () ! {IO} {
let dist = M.fromList([((0, 0), 0), ((0, 1), 1), ((1, 1), 2)])
println("tuple key (1, 1): ${show(M.lookup(dist, (1, 1)))}")
println("missing (5, 5): ${show(M.member(dist, (5, 5)))}")
println("keys: ${show(M.keys(dist))}")
let roles = M.insert(M.empty(), { name: "alice", team: 1 }, "lead")
println("record key: ${show(M.lookup(roles, { team: 1, name: "alice" }))}")
let counts = M.fromList([(Blue, 3), (Red, 1), (Green, 2)])
println("ADT keys: ${show(M.toList(counts))}")
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/map_tuple_record_keys.ail

Key concepts:

  • Record keys ignore field order: {team: 1, name: "alice"} finds {name: "alice", team: 1}
  • Keys iterate in a deterministic canonical order
  • Function or list keys are a runtime error on every operation, never a silent false

Difference Array with accumulate​

Interval coverage, a histogram and a per-bucket max, each with one array copy:

examples/runnable/difference_array_accumulate.ail
-- Difference array and histogram with std/array.accumulate (batch update, one copy).
-- accumulate(arr, [(index, value)], combine) sets out[i] = combine(out[i], value) for
-- every write in O(n + k): the pure form of Python's `diff[lo] += 1; diff[hi] -= 1`.
module examples/runnable/difference_array_accumulate
import std/io (println)
import std/array as A
import std/list (flatMap, map, mapAccumL)
import std/string (length)

-- Running sum: turns a difference array into the covered counts.
func prefix(xs: [int]) -> [int] = match mapAccumL(\s x. (s + x, s + x), 0, xs) {
(ys, _) => ys
}

-- How many intervals [lo, hi) cover each cell 0..n-1.
func coverage(n: int, intervals: [(int, int)]) -> [int] {
let corners = flatMap(\iv. match iv {
(lo, hi) => [(lo, 1), (hi, -1)]
}, intervals)
prefix(A.toList(A.accumulate(A.make(n + 1, 0), corners, \a b. a + b)))
}

export func main() -> () ! {IO} {
println("coverage: ${show(coverage(6, [(0, 3), (2, 5), (4, 6)]))}")
let words = ["b", "a", "c", "a", "b", "a"]
let idx = \w. if w == "a" then 0 else if w == "b" then 1 else 2
let hist = A.accumulate(A.make(3, 0), map(\w. (idx(w), 1), words), \a b. a + b)
println("histogram a/b/c: ${show(hist)}")
let longest = A.accumulate(A.make(2, ""), [(0, "ab"), (0, "abcd"), (1, "x")], \a b. if length(b) > length(a) then b else a)
println("max per bucket: ${show(longest)}")
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/difference_array_accumulate.ail

Key concepts:

  • accumulate(arr, [(i, x)], combine) sets out[i] = combine(out[i], x) in list order, O(n + k)
  • Works for any element type; out-of-bounds indexes are errors

Building Arrays and Maps (Cost Model)​

Values are immutable, so A.set, A.append, M.insert and acc ++ [x] each copy the whole structure. Doing one per loop step is quadratic. Build the structure once instead. See Arrays:

examples/runnable/bulk_build_cost_model.ail
-- bulk_build_cost_model.ail - cost model: build an Array or Map ONCE instead of updating it per step.
-- A.set, A.append, M.insert and acc ++ [x] each make an O(n) copy, so one per loop step is quadratic.
-- Build once: produce the whole list (map/flatMap/range, mapAccumL for running state), then
-- A.fromList / M.fromList; apply many writes with ONE A.updateMany. Lookups stay O(1).
module examples/runnable/bulk_build_cost_model
import std/io (println)
import std/list (map, flatMap, foldl, range, mapAccumL)
import std/array as A
import std/map as M

export func main() -> () ! {IO} {
let n = 2000
-- SLOW (quadratic): one O(n) copy per step
let slowArr = foldl(\acc i. A.set(acc, i, i * i), A.make(n, 0), range(0, n))
let slowMap = foldl(\acc i. M.insert(acc, i, i * i), M.empty(), range(0, n))
-- FAST (build once): O(n) in total
let fastArr = A.fromList(map(\i. i * i, range(0, n)))
let fastMap = M.fromList(map(\i. (i, i * i), range(0, n)))
println(show(A.toList(slowArr) == A.toList(fastArr)))
println(show(M.lookup(slowMap, 1999) == M.lookup(fastMap, 1999)))
-- 2D grid: one flat Array, cell (r, c) at r * w + c
let w = 4
let grid = A.fromList(flatMap(\r. map(\c. r * 10 + c, range(0, w)), range(0, 3)))
println(show(A.get(grid, 2 * w + 1)))
-- many writes: ONE copy; a later write to the same index wins
let g2 = A.updateMany(grid, [(0, 99), (5, 7), (0, 1)])
println(show(A.get(g2, 0)))
-- running state while emitting a list: mapAccumL, never acc ++ [x]
match mapAccumL(\s x. (s + x, s + x), 0, [1, 2, 3]) {
(prefix, total) => println("${show(prefix)} ${show(total)}")
}
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/bulk_build_cost_model.ail

Key concepts:

  • Lookups cost O(1): A.get, M.lookup, M.member, list nth
  • Building in one pass costs O(n): A.fromList, M.fromList, A.updateMany, mapAccumL
  • A 2D grid is one flat Array, with cell (r, c) at index r * w + c

Advanced Examples​

Higher-Order Functions​

Functions are first-class values:

examples/runnable/lambdas_higher_order.ail
-- Showcase: Higher-Order Functions
-- This example demonstrates functions that take or return functions.
module examples/runnable/lambdas_higher_order

export func main() -> () ! {IO} =
let _ = println("=== Higher-Order Functions ===") in
-- Function composition
let compose = \f. \g. \x. f(g(x)) in
let double = \x. x * 2 in
let addOne = \x. x + 1 in
let doubleThenAddOne = compose(addOne)(double) in
let _ = println("Function composition:") in
let _ = println(" doubleThenAddOne(5) = ${show(doubleThenAddOne(5))}") in
let _ = println(" (first double, then add one)") in
-- Map-like function over a pair
let applyToBoth = \f. \x. \y. [f(x), f(y)] in
let square = \x. x * x in
let result = applyToBoth(square)(3)(4) in
let _ = println("") in
let _ = println("Apply function to both values:") in
let _ = println(" applyToBoth(square)(3)(4) = ${show(result)}") in
-- Function that returns a function
let makeOperation = \op. \x. \y. op(x)(y) in
let add = \x. \y. x + y in
let multiply = \x. \y. x * y in
let adder = makeOperation(add) in
let multiplier = makeOperation(multiply) in
let _ = println("") in
let _ = println("Function returning function:") in
let _ = println(" adder(5)(3) = ${show(adder(5)(3))}") in
let _ = println(" multiplier(5)(3) = ${show(multiplier(5)(3))}") in
-- Applying a function twice
let twice = \f. \x. f(f(x)) in
let increment = \x. x + 1 in
let quadruple = twice(double) in
let _ = println("") in
let _ = println("Applying function twice:") in
let _ = println(" twice(increment)(5) = ${show(twice(increment)(5))}") in
println(" quadruple(5) = ${show(quadruple(5))}")
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/lambdas_higher_order.ail

Key concepts:

  • \x. x * 2 is a lambda function
  • Functions can be passed as arguments
  • Function composition: \f. \g. \x. f(g(x))
  • Closures capture environment

Mutual Recursion​

Multiple functions can call each other:

examples/runnable/recursion_mutual.ail
-- recursion_mutual.ail
-- Demonstrates mutually recursive functions
-- Status: ✅ Working (M-R4 recursion support)

module examples/runnable/recursion_mutual
import std/io (println)

-- Mutually recursive functions to test even/odd
-- Now supported! M-TESTING-DEPS enables testing mutually recursive functions
export pure func isEven(n: int) -> bool
tests [
(0, true),
(1, false),
(2, true),
(10, true),
(17, false)
] {
if n == 0 then true else isOdd(n - 1)
}

export pure func isOdd(n: int) -> bool
tests [
(0, false),
(1, true),
(2, false),
(10, false),
(17, true)
] {
if n == 0 then false else isEven(n - 1)
}

export func main() -> () ! {IO} {
let even42 = isEven(42)
let odd42 = isOdd(42)
let even17 = isEven(17)
let odd17 = isOdd(17)
println("isEven(42) = ${show(even42)}")
println("isOdd(42) = ${show(odd42)}")
println("isEven(17) = ${show(even17)}")
println("isOdd(17) = ${show(odd17)}")
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/recursion_mutual.ail

Key concepts:

  • pure func declares functions without side effects
  • Functions can reference each other (mutual recursion)
  • Built-in tests verify correctness: tests [(0, true), (1, false), ...]

Loops with a Local letrec​

A loop is a local recursive lambda with accumulator parameters. The recursive call is a tail call, so a million iterations run in constant stack:

examples/runnable/local_letrec_loop.ail
-- local_letrec_loop.ail
-- A loop written as a local `letrec` with an accumulator, run over 1..1,000,000.
-- The recursive call is a tail call, so the loop runs in constant stack on
-- both engines, and it runs natively on the bytecode VM: `ailang run
-- --strict-bytecode` prints the same output as `ailang run`.
module examples/runnable/local_letrec_loop

-- Sum of the multiples of k in 1..n.
func sumMultiples(k: int, n: int) -> int {
-- The recursive call to loop is a tail call: nothing runs after it.
letrec loop = \i acc. if i > n then acc else loop(i + 1, if i % k == 0 then acc + i else acc)
loop(1, 0)
}

-- Two accumulators at once: how many numbers in 1..n are odd, and their sum.
func oddStats(n: int) -> (int, int) {
-- Both recursive calls are tail calls.
letrec loop = \i count total. if i > n then (count, total) else if i % 2 == 1 then loop(i + 1, count + 1, total + i) else loop(i + 1, count, total)
loop(1, 0, 0)
}

func describe(stats: (int, int)) -> string = match stats {
(count, total) => "${show(count)} odd numbers, sum ${show(total)}"
}

-- println is in the prelude of an entry module, so no import is needed.
export func main() -> () ! {IO} {
println("multiples of 3 up to 1000000: ${show(sumMultiples(3, 1000000))}")
println("1..1000000: ${describe(oddStats(1000000))}")
}
View source on GitHub

Run it:

ailang run --caps IO examples/runnable/local_letrec_loop.ail
ailang run --caps IO --strict-bytecode examples/runnable/local_letrec_loop.ail # same output, on the bytecode VM

Key concepts:

  • letrec loop = \i acc. ... names a lambda that can call itself
  • A call in tail position (the whole result of a branch) reuses the frame
  • Local letrec and prelude println without an import both run natively under --bytecode / --strict-bytecode

Try It Yourself​

In the Playground​

Visit the Playground to run code interactively in your browser.

With CLI​

Install AILANG and run examples locally:

# Install (macOS Apple Silicon)
curl -L https://github.com/sunholo-data/ailang/releases/latest/download/ailang-darwin-arm64.tar.gz | tar -xz
sudo mv ailang /usr/local/bin/

# Or build from source
git clone https://github.com/sunholo-data/ailang && cd ailang && make install

# Run an example
ailang run --caps IO examples/runnable/hello.ail

# Interactive REPL
ailang repl

From GitHub​

Clone the repository for all 98+ examples:

git clone https://github.com/sunholo-data/ailang
cd ailang

# Run specific examples
ailang run --caps IO examples/runnable/recursion_factorial.ail

Implementation Status​

This section tracks AILANG's implementation progress and is automatically updated by CI/CD.

The example verification status shows what percentage of AILANG features are fully implemented and working. Each example exercises specific language features, so the pass rate directly reflects implementation completeness.

Status​

Examples

Example Verification Status​

Last updated: 2026-11-04 (Auto-updated by CI)

Summary: 265 passed, 0 failed, 10 skipped (Total: 275)

Overall: 265/275 examples working (96%)

Example FileStatusNotes
runnable/adt_list_fields.ail✅ Pass
runnable/adt_option.ail✅ Pass
runnable/adt_simple.ail✅ Pass
runnable/adt_tree.ail✅ Pass
runnable/ai_caching.ail✅ Pass
runnable/ai_call.ail⏭️ SkipTest/demo file
runnable/ai_call_json_simple_result.ail✅ Pass
runnable/ai_call_result.ail✅ Pass
runnable/ai_call_speech.ail✅ Pass
runnable/ai_call_stream.ail✅ Pass
runnable/ai_effect.ail✅ Pass
runnable/ai_image_generation.ail✅ Pass
runnable/ai_offline_cli.ail✅ Pass
runnable/ai_stream_openai.ail✅ Pass
runnable/ai_streaming.ail✅ Pass
runnable/ai_streaming_effect_rows.ail✅ Pass
runnable/ai_tool_loop.ail✅ Pass
runnable/ai_vision_input.ail✅ Pass
runnable/arithmetic.ail✅ Pass
runnable/array_adt.ail✅ Pass
runnable/array_basic.ail✅ Pass
runnable/array_float_kernels.ail✅ Pass
runnable/array_grid.ail✅ Pass
runnable/audio_checked.ail✅ Pass
runnable/batch_processing.ail✅ Pass
runnable/bitwise.ail✅ Pass
runnable/block_demo.ail✅ Pass
runnable/block_recursion.ail✅ Pass
runnable/bounded_take_flatmap.ail✅ Pass
runnable/bug_float_comparison.ail✅ Pass
runnable/bulk_build_cost_model.ail✅ Pass
runnable/bytes_base64url.ail✅ Pass
runnable/claude_haiku_call.ail⏭️ SkipTest/demo file
runnable/cli_args_demo.ail✅ Pass
runnable/closures.ail✅ Pass
runnable/complex_types.ail✅ Pass
runnable/cons_expression.ail✅ Pass
runnable/contracts/access_control.ail✅ Pass
runnable/contracts/basic.ail✅ Pass
runnable/contracts/cross_function.ail✅ Pass
runnable/contracts/cross_module_functions.ail✅ Pass
runnable/contracts/cross_module_functions_lib.ail⏭️ SkipTest/demo file
runnable/contracts/cross_module_types.ail✅ Pass
runnable/contracts/cross_module_types_lib.ail✅ Pass
runnable/contracts/empty_list_sort_verify.ail✅ Pass
runnable/contracts/ensures_violation_demo.ail✅ Pass
runnable/contracts/finance.ail✅ Pass
runnable/contracts/hof_verify.ail✅ Pass
runnable/contracts/inbox_injection.ail✅ Pass
runnable/contracts/inbox_injection_v2.ail✅ Pass
runnable/contracts/inbox_v2_app.ail✅ Pass
runnable/contracts/inbox_v2_lib.ail✅ Pass
runnable/contracts/insurance.ail✅ Pass
runnable/contracts/interpolation_verify.ail✅ Pass
runnable/contracts/invoice.ail✅ Pass
runnable/contracts/list_recursive_verify.ail✅ Pass
runnable/contracts/list_verify.ail✅ Pass
runnable/contracts/nested_record_verify.ail✅ Pass
runnable/contracts/nullary_constant_verify.ail✅ Pass
runnable/contracts/park.ail✅ Pass
runnable/contracts/per_function_depth_verify.ail✅ Pass
runnable/contracts/quantifier_verify.ail✅ Pass
runnable/contracts/record_adt_cycle_verify.ail✅ Pass
runnable/contracts/record_adt_sort_verify.ail✅ Pass
runnable/contracts/record_discovery_verify.ail✅ Pass
runnable/contracts/record_pattern_verify.ail✅ Pass
runnable/contracts/record_verify.ail✅ Pass
runnable/contracts/recursive_verify.ail✅ Pass
runnable/contracts/result_error_guard.ail✅ Pass
runnable/contracts/scoring.ail✅ Pass
runnable/contracts/shapes_verify.ail✅ Pass
runnable/contracts/showcase.ail✅ Pass
runnable/contracts/string_verify.ail✅ Pass
runnable/contracts/temperature.ail✅ Pass
runnable/contracts/unencodable_callee_skip.ail✅ Pass
runnable/conway_grid.ail✅ Pass
runnable/crypto_hashing.ail✅ Pass
runnable/cycle_detection_visited_set.ail✅ Pass
runnable/debug_effect.ail✅ Pass
runnable/debug_types_demo.ail✅ Pass
runnable/decide_jev.ail✅ Pass
runnable/demo_ai_api.ail✅ Pass
runnable/demos/adt_pipeline.ail✅ Pass
runnable/demos/hello_io.ail✅ Pass
runnable/difference_array_accumulate.ail✅ Pass
runnable/directory_listing.ail✅ Pass
runnable/directory_ops.ail✅ Pass
runnable/effect_latent_function_values.ail✅ Pass
runnable/effect_latent_nested_callbacks.ail✅ Pass
runnable/effect_row_var_noisy_twice.ail✅ Pass
runnable/effect_row_var_pure_caller.ail✅ Pass
runnable/effectful_list.ail✅ Pass
runnable/effectful_list_t1_mapE_basic.ail✅ Pass
runnable/effectful_list_t2_filterE_bool.ail✅ Pass
runnable/effectful_list_t3_foldlE_acc.ail✅ Pass
runnable/effectful_list_t4_flatMapE_expand.ail✅ Pass
runnable/effectful_list_t5_forEachE_unit.ail✅ Pass
runnable/effectful_list_t6_pure_flatMap.ail✅ Pass
runnable/effectful_list_t7_chain_combinators.ail✅ Pass
runnable/effectful_list_t8_string_list.ail✅ Pass
runnable/effects_basic.ail✅ Pass
runnable/effects_fs_io.ail✅ Pass
runnable/effects_pure.ail✅ Pass
runnable/exit_code.ail⏭️ SkipTest/demo file
runnable/explicit_empty_callback_contracts.ail✅ Pass
runnable/factorial.ail✅ Pass
runnable/float_int_literals.ail✅ Pass
runnable/fnv1a.ail✅ Pass
runnable/fs_bytes_roundtrip.ail✅ Pass
runnable/fs_walk_glob.ail✅ Pass
runnable/func_expressions.ail✅ Pass
runnable/game_npc_dialogue.ail✅ Pass
runnable/guards_basic.ail✅ Pass
runnable/guards_module.ail✅ Pass
runnable/hello.ail✅ Pass
runnable/html_parser.ail✅ Pass
runnable/http_put_bytes.ail✅ Pass
runnable/http_simple.ail✅ Pass
runnable/if_else_chain.ail✅ Pass
runnable/imported_adt_types.ail✅ Pass
runnable/imports.ail✅ Pass
runnable/imports_basic.ail✅ Pass
runnable/json_array_extraction.ail✅ Pass
runnable/json_basic_decode.ail✅ Pass
runnable/json_bool_encoding.ail✅ Pass
runnable/json_helpers.ail✅ Pass
runnable/json_jint.ail✅ Pass
runnable/json_parsing.ail✅ Pass
runnable/jwt_decode.ail✅ Pass
runnable/lambdas.ail✅ Pass
runnable/lambdas_advanced.ail✅ Pass
runnable/lambdas_closures.ail✅ Pass
runnable/lambdas_curried.ail✅ Pass
runnable/lambdas_higher_order.ail✅ Pass
runnable/letrec_local_shadow.ail✅ Pass
runnable/letrec_recursion.ail✅ Pass
runnable/list_extremes.ail✅ Pass
runnable/list_helpers.ail✅ Pass
runnable/list_pattern_cons.ail✅ Pass
runnable/list_pattern_records.ail✅ Pass
runnable/list_patterns.ail✅ Pass
runnable/list_safe_indexing.ail✅ Pass
runnable/list_sum.ail✅ Pass
runnable/local_letrec_loop.ail✅ Pass
runnable/mapAccumL_running_total.ail✅ Pass
runnable/map_basic.ail✅ Pass
runnable/map_strict_parity.ail✅ Pass
runnable/map_tuple_record_keys.ail✅ Pass
runnable/match_arm_block.ail✅ Pass
runnable/match_arm_block_io.ail✅ Pass
runnable/match_in_block.ail✅ Pass
runnable/math_trig.ail✅ Pass
runnable/mcp_tools.ail⏭️ SkipTest/demo file
runnable/micro_block_if.ail✅ Pass
runnable/micro_block_seq.ail✅ Pass
runnable/micro_io_echo.ail✅ Pass
runnable/micro_option_map.ail✅ Pass
runnable/micro_record_person.ail✅ Pass
runnable/module_let_helpers.ail✅ Pass
runnable/nested_match_minimal.ail✅ Pass
runnable/nested_match_simple.ail✅ Pass
runnable/nested_patterns.ail✅ Pass
runnable/net_scope_public.ail✅ Pass
runnable/no_loops_filter_map.ail✅ Pass
runnable/no_loops_fold.ail✅ Pass
runnable/no_loops_recursion.ail✅ Pass
runnable/option_demo.ail✅ Pass
runnable/parser_block_trailing_record.ail✅ Pass
runnable/pattern_sugar.ail✅ Pass
runnable/patterns.ail✅ Pass
runnable/poly_adt_result_type.ail✅ Pass
runnable/polymorphic_adt.ail✅ Pass
runnable/polymorphic_comparison_simple.ail✅ Pass
runnable/polymorphic_lambdas_phase1.ail✅ Pass
runnable/process_cancel.ail✅ Pass
runnable/process_demo.ail✅ Pass
runnable/process_policy_cancel.ail✅ Pass
runnable/process_policy_worker.ail✅ Pass
runnable/process_spawn_result.ail✅ Pass
runnable/process_stdin_write.ail✅ Pass
runnable/process_subcmd_allowlist.ail✅ Pass
runnable/property_differential_testing.ail✅ Pass
runnable/record_in_match.ail✅ Pass
runnable/record_patterns.ail✅ Pass
runnable/record_update.ail✅ Pass
runnable/record_width_subtyping.ail✅ Pass
runnable/records.ail✅ Pass
runnable/recursion_factorial.ail✅ Pass
runnable/recursion_fibonacci.ail✅ Pass
runnable/recursion_match.ail✅ Pass
runnable/recursion_mutual.ail✅ Pass
runnable/recursion_quicksort.ail✅ Pass
runnable/regex_basics.ail✅ Pass
runnable/reserved_keyword_names.ail✅ Pass
runnable/secrets/gated_secret.ail⏭️ SkipTest/demo file
runnable/secrets/leak_attempt.ail⏭️ SkipTest/demo file
runnable/secrets/positive_label_call.ail✅ Pass
runnable/secrets/scoped_declassify.ail✅ Pass
runnable/secrets/secret_demo.ail⏭️ SkipTest/demo file
runnable/secrets/sink_function_value.ail⏭️ SkipTest/demo file
runnable/secrets/sink_function_value_ok.ail✅ Pass
runnable/serve_api_mcp_app.ail✅ Pass
runnable/serve_api_mcp_file.ail✅ Pass
runnable/serve_api_mcp_header_auth.ail✅ Pass
runnable/serve_api_mcp_hints.ail✅ Pass
runnable/serve_api_mcp_oauth.ail✅ Pass
runnable/serve_api_named_params.ail✅ Pass
runnable/serve_api_response_headers.ail✅ Pass
runnable/serve_api_webhook.ail✅ Pass
runnable/set_operations.ail✅ Pass
runnable/simple.ail✅ Pass
runnable/simple_func_match.ail✅ Pass
runnable/split_argument_order.ail✅ Pass
runnable/split_map_join.ail✅ Pass
runnable/splitmix64.ail✅ Pass
runnable/std_audio_brief.ail✅ Pass
runnable/std_deflate_pdf_objstm.ail✅ Pass
runnable/stdlib_demo.ail✅ Pass
runnable/stdlib_demo_simple.ail✅ Pass
runnable/stdlib_embedding.ail✅ Pass
runnable/stdlib_game.ail✅ Pass
runnable/stdlib_gzip.ail✅ Pass
runnable/stdlib_sharedindex.ail✅ Pass
runnable/stdlib_simhash.ail✅ Pass
runnable/stdlib_smoke.ail✅ Pass
runnable/stream_multi_source.ail✅ Pass
runnable/stream_process_cancel.ail✅ Pass
runnable/stream_process_source.ail✅ Pass
runnable/stream_sse.ail✅ Pass
runnable/stream_websocket.ail✅ Pass
runnable/string_chars.ail✅ Pass
runnable/string_contains.ail✅ Pass
runnable/string_format_fixed.ail✅ Pass
runnable/string_interp_nested.ail✅ Pass
runnable/string_interpolation.ail✅ Pass
runnable/string_parsing.ail✅ Pass
runnable/string_repeat.ail✅ Pass
runnable/string_split.ail✅ Pass
runnable/structured_ai_basic.ail✅ Pass
runnable/structured_ai_schema.ail✅ Pass
runnable/syntax_ai_forgiving.ail✅ Pass
runnable/tail_recursion_loop.ail✅ Pass
runnable/tar_gzip_reader.ail✅ Pass
runnable/terminal_info.ail✅ Pass
runnable/terminal_keys.ail✅ Pass
runnable/terminal_line_input.ail✅ Pass
runnable/test_cli_io.ail✅ Pass
runnable/test_fizzbuzz.ail✅ Pass
runnable/test_guard_bool.ail✅ Pass
runnable/test_import_func.ail✅ Pass
runnable/test_io_builtins.ail✅ Pass
runnable/test_module_minimal.ail✅ Pass
runnable/type_classes.ail✅ Pass
runnable/type_inference.ail✅ Pass
runnable/type_inference_regression.ail✅ Pass
runnable/typeclasses.ail✅ Pass
runnable/url_encode.ail✅ Pass
runnable/uuid.ail✅ Pass
runnable/values_basic.ail✅ Pass
runnable/visited_set_bfs.ail✅ Pass
runnable/vm_strict_pure_builtins.ail✅ Pass
runnable/web_search.ail⏭️ SkipTest/demo file
runnable/xml_build.ail✅ Pass
runnable/xml_escape.ail✅ Pass
runnable/xml_fold.ail✅ Pass
runnable/xml_lenient.ail✅ Pass
runnable/xml_parser.ail✅ Pass
runnable/xml_space_preserve.ail✅ Pass
runnable/xml_walk_perf.ail✅ Pass
runnable/xml_zip_roundtrip.ail✅ Pass
runnable/yaml_config.ail✅ Pass
runnable/yaml_roundtrip.ail✅ Pass
runnable/zip_build_in_memory.ail✅ Pass
runnable/zip_reader.ail✅ Pass
runnable/zip_xml_fold.ail✅ Pass

Known Limitations​

Some examples may fail due to features still under development. See the maintained LIMITATIONS.md for the current list of known issues and workarounds.


Contributing Examples​

Found a bug? Have a cool example to share?


Next Steps​

See Also​