A practical functional language
with composable effects
Write pure functions, handle the rest with composable effects.
Change behavior without rewriting business logic.
Full type safety. Powered by the BEAM.
fun get_users : Unit -> List User needs {Database}
get_users () = query! "SELECT * FROM users"
# Same function call, two different behaviors:
main () = get_users () with postgres
test "get_admins" (fun () -> {
let users = get_users () with mock_db
assert_eq (List.length users) 2
})CORE CAPABILITIES
Algebraic Effects
Effects are interfaces. Handlers are implementations. Swap them for testing, middleware, or error recovery.
Full Type Inference
Strong static types with inference, traits, and effect tracking. Annotate public APIs; let the compiler infer the rest.
Pattern Matching & ADTs
Exhaustive matching, algebraic data types, records, and pure guards. Safety by design.
Typesafe BEAM Concurrency
Build with lightweight processes, OTP supervision, distribution, and statically checked message passing.
Effects in action
The true power of Saga lies in how it decouples the declaration of what needs to happen from the execution of how it happens.
Read the guide →example.saga
# Handlers can do more than mock dependencies:
effect Choose {
fun choose : List a -> a
}
outfit () = {
let top = choose! ["white", "black"]
let bottom = choose! ["jeans", "khakis"]
top <> " + " <> bottom
}
# All combinations
outfit () with all_choices
# => "white + jeans", "white + khakis",
# "black + jeans", "black + khakis"
# Pick one at random
outfit () with random
# => "black + jeans"