ROP and BOP: From Transformation to Existence
Unix gave us pipes. Functional programming gave us Result. What if the domain doesn’t need either?
The Pipeline
The core of Railway Oriented Programming is simple. A workflow is a pipeline. Failure is just another track.
Input → validate → extract → identify → save
↓ ↓ ↓ ↓
Error Error Error Error
cat | grep | sort flows text through transformations. ROP flows domain data through functions — with error handling made explicit in the type system.
A TypeScript example:
const workflow: WorkFlow = (command) =>
ok(command)
.andThen(validateReservationEvent)
.andThen(extractActualVisitor)
.asyncAndThen(identifyCustomer(findIdenticalCustomer))
.andThen(importReservationEvent)
Each stage has its own type:
UnvalidatedCommand
→ SiteReservationValidated
→ VisitorExtracted
→ CustomerIdentified
→ SiteReservationEventImported
The functional concern is data transformation. ROP gives that transformation a failure context. Result types make errors explicit. Union types eliminate impossible states. Immutability prevents corruption.
The Resonance
Place a Be Framework chain next to it.
OrderInput → OrderValidated → PaymentProcessed → OrderConfirmed
Union types constrain what can exist. Immutable. Each transition explicit. Different starting points, similar structures.
The Subject
The resemblance is structural. The difference is grammatical.
// ROP
const archived = archiveCustomer(customer)
// BOP
$becoming(new PatientArrival($vitals))
In ROP, extractActualVisitor(command). In BOP, a PatientArrival encounters a triage protocol and becomes an EmergencyCase.
The ROP workflow is a conductor with a score. In BOP, each being declares #[Be]. Nobody knows the whole.
The Question
ROP asks: did this transformation succeed or fail?
How to handle the error. How to propagate failure. How to compose functions that might fail. A HOW question.
BOP asks: can this exist at all?
An Email doesn’t get validated and produce Result<Email, Error>. It exists, or it doesn’t. There is no error track — there is no track. Semantic variables define a world where invalid values cannot be. A WHETHER question.
From this shift in question, self-proving existence, self-determined relations, and choreography all follow.
Accumulation
ROP solved a real problem.
BOP doesn’t solve that problem. It moves where the question is.
The two look at the same landscape from different elevations. From one, you see tracks and switches. From the other, the trains were never separate from the rails.
- Railway Oriented Programming — Scott Wlaschin
- TypeScript 関数型スタイルでバックエンド開発のリアル — Naoya Ito (TSKaigi 2024)