Id is a container for one value, without an additional computational context. It gives that value a map interface: each mapped function transforms the contained result, so a sequence of transformations can read as a pipeline rather than a series of intermediate assignments. section 5.1
Listing 5.5 Implementing a contextless container by extending from Array
class Id extends Array {
constructor(value) {
super(1); #1
this.fill(value);
}
}
Id.of('aabbcc') #2
.map(unique)
.map(join)
.map(toUpper)
.pop(); // 'ABC' #3
This minimal implementation extends Array, initializes one slot, and uses map to transform a string through unique, join, and toUpper. The final pop extracts the result. section 5.1
The point of the wrapper is composition, not validation: the shown Id constructor simply stores its value. Map on Id corresponds to composing functions, much as map does on Array. This lets a transformation pipeline move from functions to a value-bearing object without changing the basic composition model. section 5.1 section 5.3
Map alone is awkward when a transformation already returns an Id: mapping it can leave an Id inside another Id. With a functor implementation and flatMap, Id can instead chain container-returning functions. In the example, square and times3 each return an Id; chaining them from Id.of(2) produces 12. The shown mixin defines flatMap in terms of map and get, but the full get implementation is not shown. section 5.4.2
const square = x => Id.of(x).map(a => a ** 2); const times3 = x => Id.of(x).map(a => a * 3); Id.of(2) .flatMap(square) .flatMap(times3) .get(); // 12 Id.of(2) .flatMap(a => square(a).flatMap(times3)) .get(); // 12
Compare the direct flatMap chain with its nested form: both apply two Id-returning functions and yield 12. section 5.4.2
