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.
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.
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)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)
}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.
Install
git clone https://github.com/PhilipLudington/Kira
cd Kira && ./run-build.shWrite
effect fn main() -> void {
std.io.println("Hello, Kira!")
}Run
kira run hello.ki
# Hello, Kira!