An experimental functional language

Pure code.
Explicit effects.

A strict, purely functional language inspired by Elm, Haskell and Koka: type inference, algebraic effects, structured concurrency and metaprogramming. Programs compile to Go.

Experimental: the language is still changing.

guess.fango
1effect Prompt2    ask : String -> Int3    say : String -> ()45guess : Int ->{Prompt} ()6guess secret =7    n = ask "Your guess: "8    if n == secret then9        say "Correct!"10    else11        say (if n < secret then "Higher" else "Lower")12        guess secret

Algebraic effects.

Effects are part of function types, like a ->{Console} b, and handlers decide what they mean. Code stays in direct style.

Structured concurrency.

Spawn native tasks, await their results and communicate through channels. Scopes drain their children; cancellation is cooperative.

Metaprogramming.

Splices run hygienic, pure Fango code at compile time. Reflect on types and write your own derivers.

Small on purpose.

One compiler, local source modules and a bundled standard library. The implementation is kept small enough to read and change.

A short tour

What Fango looks like.

01

Data and patterns.

Unions and records, taken apart with case. Types are inferred, so total needs no annotation, and every match must cover all cases.

tree.fango
type Tree a = Leaf a | Branch (Tree a) (Tree a) deriving (Show)total tree =    case tree of        Leaf n -> n        Branch left right -> total left + total rightmain() =    print (total (Branch (Leaf 1) (Branch (Leaf 2) (Leaf 3))))
02

Effects and handlers.

An effect declares operations, and code calls them like functions. The handler decides what ask means and continues the computation with resume.

ask.fango
effect Ask    ask : () -> Stringgreeting _ = "Hello, #{ask ()}"main() =    print        (handle greeting () on            ask () -> resume "Fango"            return text -> text)
03

Structured concurrency.

Spawn native tasks inside an Async.run scope. The runner waits for its children and reports completion, application failure or cooperative cancellation.

tasks.fango
import Async exposing (Async)jobs : () ->{Async} (Int, Int)jobs() =    first = Async.spawn { 20 + 1 }    second = Async.spawn { 7 * 3 }    (Async.await first, Async.await second)main() = print (Async.runOutcome jobs)
04

Metaprogramming.

A deriver teaches deriving about your own classes. It runs at compile time, reflects on the type’s constructors, and generates the instance.

tag.fango
import Metaclass Tag a    tag : a -> Stringderiver Tag    tag subject valueCode =        Meta.match subject valueCode { bound -> Meta.lift bound.ctor.name }type Colour = Red | Green Int deriving (Tag)main() = print (tag (Green 3))    -- Green

Documentation

Read the docs.

An installation guide and the complete reference: the language, the standard library, and the concurrency runtime.

Install

Build from source.

Fango is experimental: the language and standard library still change. Building it requires Go 1.26:

$ git clone https://github.com/waj/fango.git
$ cd fango
$ make build
$ ./fango run examples/guess.fango