OCaml-style safety on Go’s runtime.
- Exhaustive ADTs and pattern matching
- Branded IDs (single-ctor ADTs) so
order_id≠symbol - Go interop and deploy — same runtime, stdlib, and binaries
- Cache-only builds — edit
.goop, rungoop build/goop test
type OrderAck =
| Filled of { order_id: string; qty: int }
| Rejected of { reason: string }
| PartialFill of { order_id: string; filled: int; remaining: int }
let handleAck (ack: OrderAck) : string =
match ack with
| Filled { order_id; qty } -> order_id
| Rejected { reason } -> reason
(* forgot PartialFill — Go compiles; Goop does not *)
✕ EXHAUST003: non-exhaustive match: missing constructor(s): PartialFill
cd src && go build -o ../goop ./cmd/goop
../goop check docs/examples/hello.goop
../goop build docs/examples/hello.goop # → ./goop-out (Go stays in $GOOP_HOME/build)
./goop-out
../goop test tests/Generated .go never lands in your project tree by default. See
CLI artifacts · tutorial.
Compile-time checks that Go leaves to tests, panics, or -race. Style: STYLE.md.
| Safety feature | Go | Rust | OCaml | Goop |
|---|---|---|---|---|
Sum types + exhaustive match |
❌ | ✅ | ✅ | ✅ |
No null by default (option) |
❌ | ✅ | ✅ | ✅ |
| Branded IDs (single-ctor ADT) | ❌ | ✅ | ✅ | ✅ |
| Effect handlers (OCaml 5-style) | ❌ | ❌ | ✅ | ✅ (CPS-lowered) |
| Nil channel misuse | ❌ (runtime) | N/A | N/A | ✅ (NIL001) |
| Data race detection | -race |
✅ | ❌ | ✅ (linear, conservative) |
| Refinement / contracts | ❌ | ✅ VC + optional Z3 | ||
| Native Go stdlib + deploy | ✅ | ❌ | ❌ | ✅ |
Call Go packages, implement Go interfaces in Goop, and embed Go when needed:
module main
import go "strings" {
val ToUpper : string -> string
}
@[go] {
func greet(name string) string {
return "Hello, " + name + "!"
}
}
val greet : string -> string
let main () : unit =
print_line (greet (ToUpper "goop"))
import go / import goop · implements · Go methods/fields · @[go] / @[c] embeds.
Examples: extern_demo.goop · go_method_calls.goop · go_implements_slog_handler.goop.
Everyday surface: STYLE.md · docs/examples/.
Current: v1.8.0 — cache-only goop build / compile under $GOOP_HOME/build, with transitive import goop deps. Prior highlights: Go struct/slog FFI (1.7), cross-package libraries (1.6), call lowering (1.5). Full history: CHANGELOG · RELEASE_NOTES.
Production-ready? The compiler, checker, codegen, LSP, and e2e suite ship and are exercised in CI. Some OCaml corners are pragmatic subsets; we are not claiming production load readiness yet.
Borgo / Dingo? Goop is a full compiler with OCaml-aligned syntax and compile-time safety for gradual Go migration. Dingo-style ? and F# computation expressions were removed in 1.0.
Need OCaml or Z3? No. Pattern matching from Rust/Swift/Kotlin transfers. Z3 is optional ([check] smt = true).
| Resource | Link |
|---|---|
| Tutorial | Getting started through concurrency |
| Stdlib | Prelude, builtins, std.* |
| Design | STYLE, CLI artifacts, FFI |
| Examples | Runnable; CI goop check |
| Contributing | Build and test workflow |
MIT / Apache-2.0 dual license.