The Verse Calculus: Why Failure Isn't a Boolean
The most counter-intuitive line in Lesson 11 — «if wants not a true/false switch but whether this wire can fire» — is no engineering quirk; it's a choice made in the language's core. The answer is written in the paper Epic's team published at ICFP 2023. This page gives you a look at Verse's theoretical heart.
1. One Paper, Answering One Odd Question
In 2023, Epic's language team published «The Verse Calculus: A Core Calculus for Deterministic Functional Logic Programming» at ICFP, the top conference for functional programming. The author list is star-studded: Lennart Augustsson, Joachim Breitner, Koen Claessen, Ranjit Jhala, Simon Peyton Jones (one of the guiding spirits of the Haskell language), Olin Shivers, and Epic founder Tim Sweeney himself. What the paper does is boil Verse down to a tiny set of «core rules» — small enough that, like working algebra problems back in school, you can push a Verse program forward one step at a time and account for the whole language's behavior without a gap.
The title alone lays out Verse's bloodline: it is a deterministic «functional + logic» language. The «functional» half means nearly every step of a program «computes a value», and variables are set once by default and never reassigned (genes from the Haskell family of languages). The «logic» half means a program is allowed to «find no answer» — and finding no answer is itself a controlled way for the branching to go (genes shared with Prolog).
2. Failure Is Control Flow, Not a Value
In this set of core rules, «failing» and «picking a path (choice)» are the two most basic primitive moves: any single step of evaluation either computes a result or fails — comes back empty-handed. Which branch runs is decided by «did this step produce a result», not by some true/false. This is the theoretical source of that line in Lesson 11: what if checks was never «checked or unchecked» but «did this step go through». true/false isn't even a necessity in these rules — logic merely freezes did-it-go-through into a switch value you can store in a variable, and logic{} is precisely the official bridge between those two worlds:
using { /UnrealEngine.com/Temporary/Diagnostics }
# These two lines ask completely different questions:
# "Did this evaluation of Score > 100 produce a result?" — the success/failure world
if (Score > 100):
Print("Threshold met!")
# "Seal this success/failure into a storable value" — the true/false world
HasWon := logic{Score > 100}
▸ Blueprint translation: the two halves ask two different questions. The top half is a Branch: «does the Score > 100 wire fire?» — fire, and it prints. The bottom half forks nothing at all; it seals the outcome of «does Score > 100 fire» into a switch value HasWon for later — that reverse revolving door from this lesson.
Adopt this viewpoint, and a whole batch of «odd rules» from Lesson 11 and earlier resolve in one breath. Why is = «compare» rather than «assign»? Because in this kind of language, = asks «make both sides equal / are both sides really equal» — a question that can fail, so it too is a «did it go through». Why does nearly every step «compute a value», with barely a bare command in sight? Functional bloodline. Why, when a whole if fails to go through, do the sets already made inside it get undone (the transactionality mentioned back in the variables lesson, marked <transacts>)? Picture it this way: the engine test-wires the whole stretch on a «shadow graph» first — only when every step fires does it commit to the main graph; hit a wall partway and the stretch is treated as never wired, every trace wiped. That is determinism's price, and its promise.
3. What This Means for You, Writing Code Every Day
No plans to read the paper? That's fine — one mental model alone is worth the ticket: in Verse, wherever a condition check appears, the question is always «did this step produce a result», never «is the box checked». Use it to look at the question mark in if (MyLogic?), at why «grab an element from an array by index» (Items[0]) insists on living inside an if (the index might be out of range — nothing to grab — which is also a «didn't go through»), at next lesson's failure contexts — you'll find they're all different profiles of the same face. The language isn't giving you a hard time; it simply tells one logic from start to finish.
For readers who want to dig deeper, the paper's PDF is freely readable (see Sources below), and the step-by-step derivation rules in the early sections aren't hard to follow with the examples alongside; finish it, and «Verse is kin to Haskell and Prolog» will most likely stop being a slogan and become something you can feel. It's also a handy test for whether a new language deserves deep study: does it have a core that can explain itself? Verse does — and it got published at a top venue.
Under the Verse Calculus semantics, what decides which branch an if takes?
Sources
Compiled from the openly available paper and conference materials: The Verse Calculus — Simon Peyton Jones's homepage (with PDF) ↗ · ACM Digital Library entry ↗ · ICFP 2023 conference page ↗