Validation represents a result as exactly one of two states: Success contains a value; Failure contains an error. It keeps validation rules separate from the work they guard. Instead of returning a Boolean and leaving callers to reconstruct what went wrong, a check returns a result that can carry its failure through later steps. section 5.5.3 section 5.1
The successful branch is where work happens. `map` transforms its contained value; on Failure, `map` does nothing and preserves the result. Use `flatMap` when the next function itself returns a Validation: it passes along a successful value without nesting results, or skips the remaining checks after a failure. A function must return Failure explicitly for a rejected condition; these chains do not, by themselves, make every operation exception-safe. section 5.5.4 section 5.5.5
A check with a useful failure
`checkTampering(block)` returns `Success.of(block)` when the block’s stored hash matches its calculated hash, or `Failure.of('Block hash is invalid')` otherwise. Changing the block data makes the same check report failure. A caller can inspect `isSuccess` or `isFailure` and retain the reason rather than receiving only `false`. section 5.5.3 section 5.5.5
Listing 5.21 Block validation with flatMap
class Block {
...
isValid() {
const {
index: previousBlockIndex,
timestamp: previousBlockTimestamp
} = this.#blockchain.lookUp(this.previousHash);
return Validation.of(this)
.flatMap(checkTimestamps(previousBlockTimestamp)) #1
.flatMap(checkIndex(previousBlockIndex)) #1
.flatMap(checkTampering); #1
}
}
Follow the block-validation chain: `Validation.of(this)` starts the successful path, and each `flatMap` runs another check only if the preceding check succeeded. section 5.5.5
The same interface scales beyond one block. `composeM` sequences Validation-returning functions in a point-free pipeline, whereas ordinary `compose` is for functions returning unwrapped values. A recursive `validate` method can start with an object’s own `isValid()` result, then reduce its children through `flatMap`; a failure stops later child validations. Shared `map` and `flatMap` contracts also let a custom Validation work with Ramda. Like a Promise chain, its successful path continues while an error falls through, though a Promise also models pending asynchronous work. section 5.5.6 section 5.5.7 section 5.5.8 section 8.2.2
