Go, the functional way.

The sum types, exhaustive pattern matching, and Option types Go still doesn't have — as a language, not a library. Option/Either/Try monads, zero-reflection JSON, first-class interop with every Go module, native binaries.

Try in Playground View on GitHub
sealed type Shape {
    case Circle(Radius float64)
    case Rectangle(Width float64, Height float64)
}

func area(s Shape) string = s match {
    case Circle(r)       => f"circle: ${3.14159 * r * r}%.2f"
    case Rectangle(w, h) => f"rect:   ${w * h}%.2f"
}

GALA — Go Alternative LAnguage — is a statically typed, functional-first language inspired by Scala, compiled to Go.

Safe. Ergonomic. Compatible.

The 2024 Go Developer Survey found that sum types are the #1 most-requested missing feature in Go, and Go still does not have them. GALA delivers them — and organizes everything else around three promises.

Safe — Go’s runtime bugs, caught by the compiler

Sum types with exhaustive pattern matching (an incomplete match is a build error, not a production panic), no nil (Option/Either/Try instead), immutable by default (val, immutable structs, read-only ConstPtr), always-concrete types — never a silent any — and zero-reflection typed JSON.

That extends to Go’s worst production bug class: data races are a compile error. A value crossing a goroutine boundary must be deeply immutable, and the transpiler proves it before the program runs — no sampling, no -race build, no interleaving you happened not to hit. Because GALA is immutable by default the check is silent in the common case; it fires only on genuinely mutable state (GALA-E0037).

sealed type Payment {
    case Card(Last4 string)
    case Cash()
}

func describe(p Payment) string = p match {
    case Card(n) => s"card ****$n"
    case Cash()  => "cash"
}   // omit a case and it won't compile

Ergonomic — the functional code you want to write, minus the ceremony

bind/also do-notation for composing monads, string interpolation (s"…" / f"…"), named arguments and default parameters, type inference everywhere, expression functions, and Map/Filter/FoldLeft/Collect collections. These are language features with clean syntax — not patterns bolted onto Go like samber/lo or IBM/fp-go.

func checkout(id int) Try[Receipt] {
    bind order   = fetchOrder(id)     // unwraps Try, or short-circuits
    bind payment = charge(order)
    Success(Receipt(order.Id, payment))
}

Compatible — every Go library, no bindings, native binaries

Full third-party Go interop with return types inferred directly from the Go SDK — no declaration files to write or generate. A Go (T, error) call is a Try[T] with no wrapping, the generated Go is clean and readable, and it builds to a single native binary inside your existing Go project. No runtime overhead beyond hand-written Go.

import "strconv"

// a Go (int, error) call is a Try[int]
val port = strconv.Atoi("8080").GetOrElse(80)

GALA vs Go — A Quick Look

Pattern matching is one of the most visible differences between GALA and Go. Idiomatic Go handles a closed set with a type switch, but it destructures nothing for you and never checks that every case is covered. GALA destructures values directly and enforces exhaustiveness at compile time.

GALA

val msg = shape match {
    case Circle(r)       => f"r=$r%.1f"
    case Rectangle(w, h) => f"$w%.0fx$h%.0f"
    case Point()         => "point"
}

Go

var msg string
switch s := shape.(type) {
case Circle:
    msg = fmt.Sprintf("r=%.1f",
        s.Radius)
case Rectangle:
    msg = fmt.Sprintf("%.0fx%.0f",
        s.Width, s.Height)
case Point:
    msg = "point"
}

GALA’s version is shorter, handles destructuring automatically, and produces a compile-time error if you forget a case. See the full GALA vs Go comparison for more examples including Option handling, immutable structs, and error handling.

Built with GALA: gala-tui

gala-tui demo: a build-server dashboard across eight screens

gala-tui is an Elm-architecture terminal UI framework, written from scratch in GALA. It is not a wrapper around a Go TUI library such as Bubble Tea or tview: the layout engine, differential renderer, widgets, input parsing, and async runtime are all GALA. Its only Go dependency is golang.org/x/term, for putting the terminal into raw mode. The demo above is a build-server dashboard: eight screens that between them show every widget, plus a fuzzy command palette, modals, toasts, mouse input, and four themes.

Run the demo yourself, or see the other projects built with GALA.

Features

Sealed Types

Define closed type hierarchies. The compiler rejects incomplete matches — no forgotten cases at runtime.

sealed type Shape {
    case Circle(Radius float64)
    case Rectangle(Width float64, Height float64)
}

Learn about sealed types

Built for Coding Agents

Diagnostics as JSON, every error code's reference page offline, package APIs from the terminal, and a Claude Code plugin that feeds GALA diagnostics back after every edit.

gala build --json .
gala explain GALA-E0002
gala doc collection_immutable.Array

GALA for AI agents

Compile-Time Data-Race Safety

Only deeply-immutable values may cross a goroutine boundary. A Future body that captures mutable state is a build error (GALA-E0037), not a race you find in production.

var counter = 0
Future(counter + 1)
// GALA-E0037: captures
// reassignable var "counter"

Learn about data-race safety

Structured Concurrency & Cancellation

Future[T] composes with Map/FlatMap/Zip, and bounds itself: Cancel(), WithTimeout, and Race short-circuit pending stages instead of leaking them.

val bounded = slow
    .WithTimeout(Milliseconds(500))
    .Recover((e) => 0)

Learn about concurrency

A Compiler That Works For You

Rust/Elm-style framed diagnostics with a caret and a fix. Panics report foo.gala:12, not generated Go. Self-tail-recursive functions become constant-stack loops.

error[GALA-E0035]: bare Go builtin
"len(...)" is not part of GALA's surface
  --> bare_len.gala:5:13
  |
5 |     val n = len(s)
  |             ^^^ use `.Size()`

Learn about compiler DX

Immutability by Default

val bindings are immutable. Struct fields are immutable. Auto-generated Copy() for safe updates.

struct Config(Host string, Port int)
val updated = config.Copy(Port = 8080)

Learn about immutability

Monadic Error Handling

Option[T], Either[A,B], and Try[T] replace nil checks and if err != nil with composable pipelines.

func loadConfig(path string) Config =
    os.ReadFile(path)
        .FlatMap((b) => codec.Decode(ToString(b)))
        .GetOrElse(Config(Host = "localhost"))

Learn about error handling

Monadic Binding (bind / also)

Do-notation for any monad. bind flattens FlatMap chains; also marks independent steps that accumulate errors (Validated) or run concurrently (Future).

func processOrder(id int) Try[Receipt] {
    bind o       = fetchOrder(id)
    bind valid   = validateOrder(o)
    bind payment = chargePayment(valid)
    Success(Receipt(o.Id, payment))
}

Learn about bind / also

Functional Collections

Immutable List, Array, HashMap, HashSet, TreeSet, TreeMap with Map, Filter, FoldLeft, Collect, and more.

val nums = ArrayOf(1, 2, 3, 4, 5)
val evens = nums.Filter((x) => x % 2 == 0)
val sum = nums.FoldLeft(0, (acc, x) => acc + x)

Learn about collections

Zero-Reflection JSON & YAML

Compile-time StructMeta[T] generates typed serialization with no reflection, no struct tags — for JSON and YAML alike. Builder pattern for Rename, Omit, and naming strategies.

val codec = Codec[Person](SnakeCase())
val jsonStr = codec.Encode(person).Get()
val decoded = codec.Decode(jsonStr)

Learn about JSON codec

Regex Pattern Matching

Compile-safe regex with extractors that destructure capture groups directly in match expressions. No manual group indexing.

val date = regex.MustCompile(
    "(\\d{4})-(\\d{2})-(\\d{2})")

val shown = input match {
    case date(Array(y, m, d)) =>
        s"$y/$m/$d"
    case _ => "not a date"
}

Learn about regex

Full Go Interop

Use any Go module — standard library or third-party — with no bindings. Types come straight from the Go SDK, and a Go call returning (T, error) is a Try[T].

import "github.com/google/uuid"

// uuid.Parse returns (UUID, error)
val id = uuid.Parse(raw)
    .Map((u) => u.String())
    .GetOrElse("invalid")

Learn about Go interop

IDE Support with LSP

GoLand/IntelliJ plugin with syntax highlighting, type-aware dot completion, inlay type hints, and structure view. The LSP server adds diagnostics, hover, and go-to-definition — including into Go stdlib and third-party Go module sources.

GALA code completion in IntelliJ

See IDE features

Get Started in 3 Steps

1. Install

Download a pre-built binary from Releases for Linux, macOS, or Windows, rename it to gala, and put it on your PATH. GALA compiles through Go, so you also need Go 1.25+. Nix users can run nix profile install github:martianoff/gala.

2. Write

gala new hello && cd hello

Then replace main.gala with:

package main

struct Person(Name string, Age int)

func greet(p Person) string = p match {
    case Person(name, age) if age < 18 => s"Hey, $name!"
    case _                             => s"Hello, ${p.Name}"
}

func main() {
    Println(greet(Person("Alice", 25)))
}

3. Run

gala run main.gala

gala new also writes a .claude/settings.json that enables the GALA plugin for Claude Code. For larger projects, GALA has first-class Bazel rules.

See the full Getting Started guide for project setup, Bazel integration, and dependency management.

Standard Library

GALA ships with a standard library of type-safe data structures and monads, all built on sealed types and functional programming patterns.

Types

Type Description Documentation
Option[T] Optional values — Some(value) / None() Monadic types
Either[A, B] Disjoint union — Left(a) / Right(b) Monadic types
Try[T] Failable computation — Success(value) / Failure(err) Monadic types
Future[T] Async computation with Map, FlatMap, Zip, Await, Cancel, WithTimeout Concurrency
Sendable[F] Transparent concurrency-boundary marker — compile-time capture safety Concurrency safety
Validated[E, A] Accumulating validation — Valid / Invalid, Zip2…Zip10 Monadic binding
Tuple[A, B] Tuples with (a, b) syntax and destructuring, up to Tuple10 Language spec
ConstPtr[T] Read-only pointer with compile-time enforcement Immutability
Codec[T] Zero-reflection JSON codec — Encode, Decode, Rename, Omit, pattern matching JSON codec
Regex Regular expressions with Unapply for pattern matching Regex
IO[T] Lazy composable effects — Of, Suspend, Map, FlatMap IO effect

Collections

Type Kind Key Operations Best for
List[T] Immutable O(1) prepend, O(n) index Recursive processing
Array[T] Immutable O(1) random access General-purpose sequences
HashMap[K,V] Immutable O(1) lookup Key-value storage
HashSet[T] Immutable O(1) membership Unique element collections
TreeSet[T] Immutable O(log n) sorted ops Ordered unique elements
TreeMap[K,V] Immutable O(log n) sorted ops Sorted key-value storage

All collections support Map, Filter, FoldLeft, ForEach, Exists, Find, Collect, MkString, Sorted, and more. Mutable variants are available in collection_mutable for performance-sensitive code. See the collections documentation for details.

Documentation

Document Description
Language Reference Complete reference for GALA syntax and semantics
All Documentation Documentation hub — every guide and standard-library page
Getting Started Installation, project setup, and first program
GALA vs Go Side-by-side comparison with idiomatic Go
Sealed Types Algebraic data types and closed hierarchies
Pattern Matching Exhaustive matching, destructuring, and guards
Immutability val, immutable structs, Copy(), and ConstPtr[T]
Error Handling Option[T], Either[A,B], Try[T] monads
Collections Immutable and mutable functional collections
Concurrency Future[T], Promise[T], ExecutionContext, cancellation, timeouts, Race
Concurrency Safety Compile-time data-race safety — Shareable, Sendable, GALA-E0037
Compiler DX Framed diagnostics, GALA-source stack traces, guaranteed TCO, use
Subprocess Spawn and drive child processes, with Future-returning async methods
JSON Codec Zero-reflection JSON serialization with Codec[T]
YAML Codec Zero-reflection YAML serialization with the same builder API
Regex Pattern matching with regex extractors
IO Effect Lazy, composable side effects
Go Interop Using Go libraries and types from GALA
Playground Try GALA in your browser — no install needed

Showcase Projects

Project Description
GALA TUI Flagship. Elm-architecture TUI framework built from scratch in GALA, not a wrapper around a Go TUI library — immutable widgets, differential renderer, async runtime, mouse, themes
GALA Team Multi-agent Claude CLI orchestrator — Team Lead delegates to Engineers and QAs, reviews work, hands you a PR. Its interface is a gala-tui app
GALA Server Immutable HTTP server library with builder-pattern configuration
GALA Playground Web-based playground — try it live