AILANG Examples
Learn AILANG through interactive examples. Each example demonstrates a key feature with working code you can try in the Playground.
Quick Start Examples
Hello World
The simplest AILANG program with I/O effects:
module examples/hello
import std/io (println)
fn main() !: IO -> () =
println("Hello, AILANG!")
Run it:
ailang run --caps IO --entry main examples/hello.ail
Key concepts:
-
!: IO
declares the function performs I/O -
println
is imported fromstd/io
-
--caps IO
grants I/O capability at runtime
Recursion & Pure Functions
AILANG uses recursion instead of loops for deterministic control flow:
-- Factorial: pure function, no effects
fn factorial(n: int) -> int =
if n <= 1 then 1
else n * factorial(n - 1)
-- Main: performs I/O
fn main() !: IO -> () =
println(show(factorial(5)))
Run it:
ailang run --caps IO --entry main examples/factorial.ail
Output:
120
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:
import std/io (println)
-- Sum list using pattern matching
fn sum(list: [int]) -> int =
match list {
[] -> 0,
[head, ...tail] -> head + sum(tail)
}
fn main() !: IO -> () =
let numbers = [1, 2, 3, 4, 5];
println("Sum: " ++ show(sum(numbers)))
Output:
Sum: 15
Key concepts:
-
[]
matches empty list -
[head, ...tail]
destructures list - Exhaustive matching required (compiler enforces)
Algebraic Data Types (ADTs)
Define custom types with multiple constructors:
import std/io (println)
type Tree =
| Leaf(int)
| Node(Tree, int, Tree)
-- Sum all values in tree
fn sumTree(tree: Tree) -> int =
match tree {
Leaf(n) -> n,
Node(left, value, right) ->
sumTree(left) + value + sumTree(right)
}
fn main() !: IO -> () =
let tree = Node(Leaf(1), 2, Node(Leaf(3), 4, Leaf(5)));
println("Tree sum: " ++ show(sumTree(tree)))
Output:
Tree sum: 15
Key concepts:
-
type Tree =
defines an ADT with 2 constructors - Pattern matching handles all cases
- Compiler ensures exhaustiveness
Effect System
Multiple Effects
Functions can declare multiple effects they perform:
import std/io (println)
import std/fs (readFile)
import std/json (decode)
fn loadConfig() !: IO,FS -> Result[string, string] =
do {
content <- readFile("config.json");
println("Loaded config file");
return Ok(content)
}
fn main() !: IO,FS -> () =
match loadConfig() {
Ok(content) -> println("Config: " ++ content),
Err(e) -> println("Error: " ++ e)
}
Run it:
ailang run --caps IO,FS --entry main examples/config.ail
Key concepts:
-
!: IO,FS
declares both I/O and filesystem effects -
do
blocks sequence effectful operations -
Result[T,E]
type for error handling
Effect Polymorphism
Functions can be generic over effects:
-- Works with any effect row
fn log[e](message: string) !: {IO | e} -> () =
println("[LOG] " ++ message)
-- Calls log while also reading files
fn processFile(path: string) !: IO,FS -> () =
do {
log("Reading file: " ++ path);
content <- readFile(path);
log("File loaded")
}
Key concepts:
-
!: {IO | e}
means "IO plus whatever effects the caller has" - Effect polymorphism enables reusable functions
- Effect rows compose naturally
Type System
Type Inference
AILANG infers types automatically using Hindley-Milner:
import std/io (println)
-- No type annotations needed!
fn double(x) = x * 2
fn main() !: IO -> () =
let result = double(21);
println(show(result)) -- Prints: 42
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:
import std/io (println)
type Person = { name: string, age: int }
fn greet(person: Person) !: IO -> () =
println("Hello, " ++ person.name)
fn main() !: IO -> () =
let employee = { name: "Alice", age: 30, role: "Engineer" };
greet(employee) -- OK! employee has all required fields
Key concepts:
- Records support structural typing
- Width subtyping:
{a, b, c}
⊆{a, b}
- Field access:
record.field