Skip to main content
Kira
Functional + Explicit

Kira

Pure clarity for functional programming.

Kira is a functional programming language with explicit types, explicit effects, and no surprises — designed for clarity, predictability, and AI code generation.

Clear by design

Every line is self-describing. No context needed.

shapes.ki
type Shape =
    | Circle(f64)
    | Rectangle(f64, f64)

fn area(shape: Shape) -> f64 {
    var result: f64 = 0.0
    match shape {
        Circle(r) => { result = 3.14159 * r * r }
        Rectangle(w, h) => { result = w * h }
    }
    return result
}

effect fn main() -> void {
    let s: Shape = Circle(5.0)
    std.io.println("Area: ${to_string(area(s))}")
}

Everything you need

A functional language built for clarity and correctness.

Explicit Types

Every variable, parameter, and return type is annotated. No inference ambiguity — you always know exactly what something is.

Explicit Effects

Side effects are tracked in function signatures. Pure functions cannot perform I/O — the type system enforces it.

Pattern Matching

Exhaustive pattern matching with guards, or-patterns, and destructuring. Work with data safely and expressively.

Algebraic Data Types

Sum types (tagged unions) and product types (records) let you model your domain precisely. No impossible states.

Result & Option

No null, no exceptions. Use Result[T, E] and Option[T] with the ? operator for clean, composable error handling.

Memoization

Mark pure functions with memo for automatic caching. Recursive functions like Fibonacci go from exponential to linear.

Higher-Order Functions

Functions are first-class values. Map, filter, fold — build powerful abstractions with composable function pipelines.

AI-Native

Designed for AI code generation. Explicit types and consistent syntax make Kira ideal for reliable AI-generated code.

Interactive REPL

Experiment and prototype interactively. Test ideas, check types, and explore the standard library without a compile cycle.

Three principles

Every design decision follows from these.

1

Explicit types, everywhere.

Every variable, parameter, and return type must be annotated. No type inference means no ambiguity — you never need to trace through code to understand what something is.

let x: i32 = 42           // explicit types
fn add(a: i32, b: i32) -> i32 {
    return a + b          // explicit returns
}
let result: i32 = add(x, 10)
2

Effects are visible.

Side effects are tracked in function signatures. Pure functions cannot call effect functions — the compiler enforces it. You always know which functions can do I/O at a glance.

// Pure — no side effects
fn double(n: i32) -> i32 {
    return n * 2
}

// Effect — can perform I/O
effect fn greet(name: string) -> void {
    std.io.println("Hello, " + name)
}
3

No surprises.

One obvious way to do things. No null, no exceptions, no implicit conversions, no undefined behavior. Predictable semantics you can reason about.

// No null — use Option[T]
let name: Option[string] = Some("Alice")

// No exceptions — use Result[T, E]
let result: Result[i32, string] = Ok(42)

// Logical keywords, not symbols
if a and b or not c { ... }

Up and running in minutes

Three steps from zero to your first Kira program.

1

Install

git clone https://github.com/PhilipLudington/Kira
cd Kira && ./run-build.sh
2

Write

effect fn main() -> void {
    std.io.println("Hello, Kira!")
}
3

Run

kira run hello.ki
# Hello, Kira!

Ready to try Kira?

Explore the docs, browse the examples, or dive right in.