The State of GALA: May 2026
Eleven weeks, ~55 releases, and a new tagline: GALA hits 0.50.0 with cross-package generics, an LSP, and four new stdlib packages.
Search for a command to run...
Eleven weeks, ~55 releases, and a new tagline: GALA hits 0.50.0 with cross-package generics, an LSP, and four new stdlib packages.
No comments yet. Be the first to comment.
GALA is a statically typed, functional-first language that transpiles to Go. This series tracks its evolution — the features that shipped, the rough edges that remain, and where the language is heading, one release milestone at a time.
June's 0.56 -> 0.62 releases: bind/also monadic do-notation, applicative validation with Validated, and concurrent binds over Future.
Go's race detector samples a schedule and hopes. GALA makes a value that isn't safe to share across goroutines a build failure.
June's 0.56 -> 0.62 releases: bind/also monadic do-notation, applicative validation with Validated, and concurrent binds over Future.
Importing a third-party Go module through Bazel and rules_gala - with concrete types across the seam, verified hands-on.
From rules welded inside the language repo to a standalone, registry-published rules_gala with a real toolchain and Gazelle BUILD generation.
A follow-up to The State of GALA: March 2026.
In March I wrote up where GALA stood: version 0.25.2, a couple of months old, 46 releases deep, with a rich standard library, a zero-reflection JSON codec, and async primitives. I also said GALA was "still young" and named its roughest edge by name — complex generic type inference across package boundaries — and listed four near-term priorities: stability, cross-package generics, IDE support, and a package registry.
Eleven weeks later GALA is at 0.50.0. Another ~55 releases shipped in that window, which works out to roughly one a working day — the cadence from the first two months held. More interesting than the version number is what changed underneath it. Three of the four roadmap items landed (one of them more thoroughly than I'd planned), the standard library grew four new packages, the build system got a real caching layer, and — the part I keep coming back to — the one-line pitch changed.
In March, the README led with the backronym: GALA, the Go Alternative LAnguage. Accurate, but it told you what GALA isn't (plain Go) rather than what it is. The tagline now reads:
Scala on Go.
That's a sharper, more honest claim, and it's the one people actually reacted to. GALA is a statically typed, functional-first language with sealed types, exhaustive pattern matching, immutable collections, and a real monad stack — Option, Either, Try, Future, IO — that happens to compile to readable Go and keep the entire Go ecosystem working unchanged. If you've written Scala, Kotlin, F#, or OCaml and then had to go back to Go, you know exactly the gap GALA is trying to close.
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 area: ${3.14159 * r * r}%.2f"
case Rectangle(w, h) => f"rect area: ${w * h}%.2f"
}
The rename isn't marketing varnish over the same code. It's a bar. "Scala on Go" sets an expectation — the type system should hold up across files and packages, the standard library should feel functional end to end, the tooling should exist — and the last eleven weeks were largely about earning it.
1. Stability and the type-inference regression suite — done, and then some. In March the type-inference regression suite had 14 cases. The bulk of the ~190 non-merge commits since are fixes and the regression guards that lock them in: cross-package Try chains, two-parameter HashMap.ForEachKV lambdas, tuple-literal element types driven by the call-site expected type, statement-position match lowering, sealed-case widening in tuple match arms. The pattern was consistent — every reported bug became a permanent example test before the fix shipped, per the project's own rule of never working around a transpiler bug.
2. Cross-package generics — the rough edge, largely filed down. This was the honest weak spot in March, and it got the most attention. A few of the concrete fixes:
Option/Try .Map type parameters are now driven by the call-site expected type instead of being guessed locally.Alongside the fixes, GALA gained coded diagnostics. Cross-package symbols now require an explicit import, and you get a real error code — GALA-E0025 — instead of a vague resolution failure. Naming your errors is a small thing that signals a compiler growing up.
3. IDE support — shipped, and wider than promised. March promised "a GoLand plugin for syntax highlighting and navigation." What shipped is that plus a full LSP server:
gala lsp) that brings VS Code and Neovim along for the ride: real-time diagnostics (including match-exhaustiveness), hover with type signatures, go-to-definition across files, find references, type-aware completion, and inlay hints sourced from the transpiler's own VarTypes. It debounces analysis by 500ms so it stays quiet while you type.4. Package registry — still in flight. This is the one item that didn't fully land. gala mod add handles Go and GALA dependencies today, including third-party Go modules, but a first-class public registry for publishing and discovering GALA libraries is still in progress. Calling it out for the same reason I called out generics in March: the honest list is the useful one.
The theme across the new packages is functional error handling reaching the edges of the library — the I/O-shaped corners that usually get a pass and return naked (value, error) or panic. In GALA they return Try.
crypto — hashing (SHA-256/512, SHA-1, MD5), HMAC (SHA-256/512), Ed25519 signing, X25519 key exchange, and CSPRNG helpers. Hashes return a Digest you can render however you need:
val digest = crypto.Sha256{}.Hash(data) // data : Array[byte]
Println(digest.Hex())
Println(digest.Base64())
Crucially, the operations that can fail — random-byte generation, for instance — return Try[Array[byte]] rather than panicking, so a failed entropy read composes like any other fallible step instead of taking down the process.
yaml — a type-safe YAML codec that shares the exact same StructMeta[T] compiler intrinsic as the JSON codec. Same zero-reflection machinery, same builder API, no struct tags:
struct Project(Name string, Repo string, Port int)
val codec = Codec[Project](SnakeCase())
val text = codec.Encode(Project("auth", ".", 8080)).Get()
// name: auth
// repo: .
// port: 8080
val back = codec.Decode(text) // Try[Project]
fs — file operations with Try return types throughout: ReadFile/WriteFile, their string variants, ReadLines/WriteLines/AppendString for line-oriented work, and directory operations CopyFile, Rename, Walk, and Glob.
val saved = fs.WriteFileString("notes.txt", "hello", 0o644)
.FlatMap((_) => fs.AppendString("notes.txt", "\nworld", 0o644))
.FlatMap((_) => fs.ReadLines("notes.txt")) // Try[Array[string]]
path — a thin, ergonomic wrapper over path/filepath. Plus the strings package was rebuilt into an ergonomic free-function form, and subprocess was reworked to return explicit Try values instead of panicking on failure — the same edge-hardening pass that crypto got.
Concurrency picked up one notable primitive too: Future.WithTimeout is a monadic timeout that completes with the original result if it arrives in time and a TimeoutError otherwise.
val result = slowCall().WithTimeout(Seconds(5)).Await() // Try[T]
(It's honest about its limits: the timeout races the result, it doesn't cancel the underlying computation — the docstring says so plainly.)
March's headline performance number was the 22x cold-compile speedup from batch transpilation. The work since has been about the second build and every build after it:
gob for the on-disk analysis cache, with the cache busted automatically when the gala binary's content changes.The throughline is the same as the transpilation strategy itself: do the expensive analysis once, cache it honestly, and invalidate it correctly. We're also extracting the Bazel integration into a standalone rules_gala module so downstream projects can depend on it cleanly — that work is landing now.
In March the showcase was a web playground, a 7-file HTTP server, and a couple of demos. Two of the newer entries are a different order of magnitude, and both are written entirely in GALA:
These matter because they're the difference between "GALA is used somewhere in this project" and "this project is GALA." Frameworks shake out a language's ergonomics in a way that example programs never do.
| March 2026 | May 2026 | |
|---|---|---|
| Version | 0.25.2 | 0.50.0 |
| Releases (total) | 46 | ~101 |
| New stdlib packages since | — | crypto, yaml, fs, path (+ rebuilt strings) |
| Type-inference regression cases | 14 | many dozens |
| IDE tooling | roadmap | GoLand plugin + LSP (VS Code, Neovim) |
| Tagline | Go Alternative Language | Scala on Go |
Same deal as last time — the honest list:
The thing I wrote in March still holds: the transpiler is honest about what it is — a source-to-source compiler that generates readable Go, with no special cases for its own standard library. What changed is the confidence behind the pitch. In March, "GALA is like Scala but for Go" was an aspiration. At 0.50.0 — with the type system holding across packages, an LSP in your editor, a functional standard library that reaches the I/O edges, and frameworks written in the language itself — it's closer to a description.
Try it in your browser — no install — or grab a binary from Releases and gala run main.gala.