a functional & reactive language for the full stack web
| docs | ||
| editor/vscode | ||
| examples | ||
| src | ||
| stdlib | ||
| tests | ||
| .gitignore | ||
| bun.lock | ||
| mise.toml | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
catena
A functional language that compiles to TypeScript and targets Bun.
Features
Types and bindings
constbindings with optional type annotations- Full Hindley-Milner type inference — annotations are optional everywhere
- Type aliases (
alias UserId = String,alias Pair<A, B> = (A, B)) - Algebraic data types (
type Option<T> = None | Some(T)) - Record types (
{ x: Int, y: Int }), tuple types ((Int, String)) - Function types (
Int -> Int -> Bool)
Functions
- Named functions:
fn add(x: Int, y: Int): Int -> x + y - Multi-parameter functions with automatic currying
- Anonymous lambdas:
fn x -> x + 1,fn (x, y) -> x + y - Nullary functions:
fn greet() -> "hello" - Paren-free application:
f xorf(x)— both work - Pipe operator:
x ~> f ~> g(left-to-right application) - Compose operators:
f >> g(left-to-right),f << g(right-to-left)
Data structures
- Record literals:
{ name: "Alice", age: 30 } - Record spread:
{ ...base, age: 31 } - Deep path update:
{ ...user, address.city: "LA" } - Tuples:
(1, "hello", true)with static index accesspair[0] - Pattern matching on all of the above
Pattern matching
matchexpressions with exhaustiveness checking- Literal, wildcard, variable-binding, constructor, record, tuple patterns
- Or-patterns:
1 | 2 | 3 -> "small" - As-patterns:
p@(x, y) -> ... - Optional match-arm guards:
x if x > 0 -> ... - Unreachable-arm warnings
FFI / interop
- Namespace imports:
use 'node:fs' as Fs - Typed named imports with compile-time curry wrappers:
use './lib'.{ fn: A -> B } - Untyped named imports with runtime arity detection
@raw"..."— inline TypeScript in type or expression positionascasts:x as Float,x as @raw"NodeJS.ProcessEnv"
Prelude (auto-included in every program)
Option<T>,Result<E, T>,Either<L, R>,List<T>- Function combinators:
id,const_,flip - Tuple helpers:
fst,snd,swap OptionandResultcombinators:map_option,and_then_option,map_result,and_then_result, etc.printbuilt-in
Setup
bun install
Usage
Compile and run:
bun run catena examples/hello.ctn --run
Compile only (produces a .ts file next to the source):
bun run catena examples/factorial.ctn
# → examples/factorial.ts
Examples
See examples/:
| File | What it shows |
|---|---|
hello.ctn |
Hello, world |
factorial.ctn |
Recursion |
fibonacci.ctn |
Mutual recursion |
functions.ctn |
Multi-arg functions, lambdas |
records.ctn |
Records, spreads, deep path update |
tuples.ctn |
Tuples and indexing |
pattern-matching.ctn |
Match expressions and patterns |
functional.ctn |
Pipe and compose operators |
raw_and_as.ctn |
@raw escapes and as casts |
showcase.ctn |
Full feature tour: ADTs, FFI, pattern matching |
Development
Run tests:
bun test
The compiler is a single linear pipeline:
| Module | Role |
|---|---|
src/lexer.ts |
Source string → tokens |
src/parser.ts |
Tokens → CST (Chevrotain grammar) |
src/cst-to-ast.ts |
CST → typed AST |
src/typechecker.ts |
Hindley-Milner inference + exhaustiveness checking |
src/backends/typescript.ts |
AST → TypeScript |
src/codegen.ts |
Backend registry and dispatch |
src/compile.ts |
Wires pipeline together |
src/cli.ts |
Command-line entry point |
stdlib/src/prelude.ctn |
Auto-included standard types and combinators |