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:
-- 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!")
Run it:
ailang run --caps IO examples/runnable/hello.ail
Key concepts:
-
! {IO}declares the function performs I/O -
printlnis imported fromstd/io -
--caps IOgrants I/O capability at runtime
Recursion & Pure Functions
AILANG uses recursion instead of loops for deterministic control flow:
-- 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))
}
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:
-
factorialis 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:
-- 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))
Run it:
ailang run examples/runnable/list_sum.ail
Output:
(15, 5)
Key concepts:
-
INilmatches empty list -
ICons(head, tail)destructures list -
letrecenables recursive function definitions - Exhaustive matching required (compiler enforces)
Algebraic Data Types (ADTs)
Define custom types with multiple constructors:
-- 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)))
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 funcdeclares functions without side effects - Pattern matching handles all cases
- Compiler ensures exhaustiveness
Effect System
Multiple Effects
Functions can declare multiple effects they perform:
-- 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)
}
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:
-- 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))
Run it:
ailang run --caps IO examples/runnable/type_inference.ail
Key concepts:
- Type inference works across function boundaries
- Explicit annotations optional but recommended
-
:typecommand in REPL shows inferred types
Records & Subsumption
Records are structural types with width subtyping:
-- 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
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
JSON & HTTP
JSON Parsing
Parse and work with JSON data:
-- 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)
}
}
Run it:
ailang run --caps IO examples/runnable/json_parsing.ail
Key concepts:
-
decodereturnsResult[Json, string] - Pattern match on JSON structure using
Ok/Err - Use
getandasStringhelpers for field access
HTTP Requests
Make HTTP requests with the Net effect:
-- 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")
}
Run it:
ailang run --caps IO,Net examples/runnable/http_simple.ail
Key concepts:
-
! {IO, Net}declares network capability -
httpGetreturns response body as string - DNS rebinding protection built-in
Advanced Examples
Higher-Order Functions
Functions are first-class values:
-- 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)))
Run it:
ailang run --caps IO examples/runnable/lambdas_higher_order.ail
Key concepts:
-
\x. x * 2is 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:
-- 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))
}
Run it:
ailang run --caps IO examples/runnable/recursion_mutual.ail
Key concepts:
-
pure funcdeclares functions without side effects - Functions can reference each other (mutual recursion)
- Built-in tests verify correctness:
tests [(0, true), (1, false), ...]
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
Example Verification Status
Last updated: 2026-01-30 (Auto-updated by CI)
Summary: 107 passed, 3 failed, 0 skipped (Total: 110)
Overall: 107/110 examples working (97%)
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
- Try the Playground - Run code in your browser
- Read the Language Reference - Complete syntax guide
- AI Integration Guide - Use AILANG with AI agents
- Browse all examples - 98+ verified examples
See Also
- Testing Guide - Write inline tests for your examples
- Debugging Guide - Troubleshoot failing examples
- Module Execution - Run modules with full effects
- Known Limitations - Current limitations and workarounds