composeM sequences functions that return monadic values. It uses flatMap to pass each intermediate result onward while flattening the wrapped values, so the monad can control the pipeline. section 5.5.6
The distinction from ordinary composition is straightforward:
- Use compose for functions returning ordinary, unwrapped values; use composeM for functions returning monads. section 5.5.6
- composeM2 applies one monad-returning function through another, and composeM reduces that binary operation across a longer pipeline. section 5.5.6
- With Validation, a failed check skips subsequent checks and carries the failure result through the chain. section 5.5.5 section 5.5.6
Block validation
A block can be validated by composing Validation.of with checks for timestamps, index, tampering, difficulty, linkage, and length. The resulting pipeline remains point-free while Validation steers success or failure. section 5.5.5 section 5.5.6
Listing 5.22 Block validation with composeM
class Block {
//...
isValid() {
const {
index: previousBlockIndex,
timestamp: previousBlockTimestamp
} = this.#blockchain.lookUp(this.previousHash);
return composeM(
checkTimestamps(previousBlockTimestamp),
checkIndex(previousBlockIndex),
checkTampering,
Validation.of
)(Object.freeze(this));
}
}
Inspect a complete composeM validation pipeline applied to an immutable block. section 5.5.6
