簡素

kanso

the language where the source contains only decisions.

examples/pipes.kso
fn greet name
  "hello, {name}"

fn main
  "kanso" . greet . print
output
hello, kanso
the founding principle
anything a style guide, linter, or code review would enforce by convention, kanso enforces by making the alternative a compile error or unrepresentable.
doctrine

six deletions

kanso is defined less by what it adds than by what it makes unnecessary. every derivable fact lives in tooling; the source keeps only what the compiler cannot know.

01

effects are values

print "hi" returns a description of printing; nothing executes until the runtime receives main's description. effect sets are inferred and propagate up the call graph — no async/await, no function coloring, zero overhead for pure calls. tests assert on descriptions; no mocks.

02

failure is a value

no exceptions, no panics — and no ok/some wrappers either. success is the bare value; err reason and none are ordinary types that propagate on their own. an err reaching main unhandled is a compile error, not a crash.

03

dispatch is the only eliminator

values may inhabit typesets, and the only way out is dispatch. no match, no instanceof, no tag tests, no narrowing syntax. overloads dispatch on literals, concrete types, or typeset guards — resolved statically, and monomorphic code carries no tags.

04

no interfaces

no interface, class, or instance construct exists. a generic function's requirements are inferred from its body — minimal by construction, transitive through call chains. the lsp renders the effective contract; publish tooling diffs it and enforces semver.

05

canonical form

one rendering per program. non-canonical whitespace is a syntax error; fields, imports, and typeset members are alphabetical, enforced. no formatter tool exists — there is nothing left to format.

06

memory without gc or borrow checker

values are immutable, so the heap is a dag, so reference counting is complete. perceus-style: counts elided statically, frees inserted at last use, in-place update under unique ownership. no lifetimes, no memory syntax in source.

real programs

see it run

every sample below is verbatim from examples/ in the repository.

examples/dispatch.kso
fn fact 0
  1

fn fact n
  n * fact (n - 1)

fn main
  answer = fact 20
  print "20! = {answer}"
output
20! = 2432902008176640000

literal 0 outranks the generic overload — the base case is dispatch, not a conditional. and int is arbitrary-precision by default, so 20! just works.

examples/records.kso
type user
  admin: bool
  name: string

fn main
  clay = user true "clay"
  print (welcome clay)

fn welcome (user _ name)
  "irasshaimase, {name}"
output
irasshaimase, clay

every type is a single-constructor record; fields are alphabetical, enforced. construction is positional and destructuring is how you take records apart.

examples/effects.kso
fn main
  print "one" >> print "two" >> print "three"
output
one
two
three

>> sequences descriptions without passing data. together with ., it is the complete vocabulary of "before" — everywhere else, the runtime owns order.

examples/lists.kso
fn describe none
  "no ninth price"

fn describe x
  "ninth price: {x}"

fn main
  prices = [30 10 20]
  doubled = map prices (x -> x * 2)
  ninth = at prices 9
  print "sorted: {sort prices}" >> print "doubled: {doubled}" >> print (describe ninth)

no panicking access anywhere: at prices 9 returns none, which propagates until a describe overload dispatches on it. sort prices needs no interface — compare derives structurally. indexing is 1-based, everywhere, no exceptions.

status

where things stand

v0.1 design freeze

the spec is gaveled

the v0.1 specification (july 2026) is the authoritative record of every design decision to date. anything marked open is not yet decided — and it says so.

phase 1

reference interpreter

a tree-walking interpreter in rust, built query-based from day one so the lsp shares the engine. phase 0 comes first: a paper proof that inference and dispatch — the language's two founding features — are mutually consistent.

honest gaps

open questions (spec §14)

  • inference fixpoint formalization
  • destructuring syntax
  • module qualification syntax
  • build totality; map literals
  • pipe-vs-rebind canonicality
  • multi-way conditional; ffi; coercion
  • process mailbox & restart details
quickstart

run it

clone, build, run. the interpreter is under construction — the examples are the golden-file corpus it is built against.

shell
$ git clone https://github.com/ClayShentrup/kanso
$ cd kanso
$ cargo build --release
$ ./target/release/kanso run examples/hello.kso
hello, world