Scala on Go.

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 that transpiles to Go.

Safe. Ergonomic. Compatible.

The 2024 Go Developer Survey found that sum types are the #1 most-requested missing feature in Go. As of Go 1.25 they still don’t exist. 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. The transpiler enforces match exhaustiveness and immutability at compile time.

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. Wrap a Go (T, error) call in Try and it becomes a Try[T], 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, wrapped into Try[int]
val port = Try(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.

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

Pattern Matching

Exhaustive pattern matching with destructuring, guards, and expression results — far beyond Go's switch.

val msg = shape match {
    case Circle(r)       => f"r=$r%.1f"
    case Rectangle(w, h) => f"${w * h}%.2f"
}

Learn about pattern matching

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.

val result = divide(10, 2)
    .Map((x) => x * 2)
    .FlatMap((x) => divide(x, 3))
    .Recover((e) => 0)

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

Default Parameters & Named Arguments

No more functional options pattern or config structs. Default parameter values and named arguments work directly in function signatures.

func connect(host string,
    port int = 8080, tls bool = true,
) Connection

connect("localhost", tls = false)

Learn about default parameters

Zero-Reflection JSON Codec

Compile-time StructMeta[T] generates typed serialization with no reflection, no struct tags. 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})")

input match {
    case date(Array(y, m, d)) =>
        s"$y/$m/$d"
}

Learn about regex

Full Go Interop

Use any Go library. Go imports, Go types, and Go functions work directly in GALA code. One ecosystem, zero friction.

import "strings"

val name = user.Name
    .Map((n) => strings.ToUpper(n))
    .GetOrElse("ANONYMOUS")

Learn about Go interop

IDE Support with LSP

GoLand/IntelliJ plugin with syntax highlighting, type-aware dot completion, inlay type hints, and structure view. LSP server provides diagnostics, hover, go-to-definition, and more.

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. Or build from source:

git clone https://github.com/martianoff/gala.git && cd gala
bazel build //cmd/gala:gala

2. Write

Create main.gala:

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 mod init example.com/hello
gala run main.gala

Or with Bazel for larger projects:

bazel run //myapp:myapp

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 Concurrency
Tuple[A, B] Pairs and triples with (a, b) syntax 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 Specification Complete reference for GALA syntax and semantics
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], and ExecutionContext
JSON Codec Zero-reflection JSON serialization with Codec[T]
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 Playground Web-based playground — try it live
State Machine Example State machines with sealed types and pattern matching
Log Analyzer Structured log parsing with Go stdlib interop and functional pipelines
GALA Server Immutable HTTP server library with builder-pattern configuration
GALA TUI Elm-architecture TUI framework — immutable widgets, differential renderer, async runtime
GALA Team Multi-agent Claude CLI orchestrator — Team Lead delegates to Engineers and QAs, reviews work, hands you a PR