doM
Monadic do-comprehension like syntax for JavaScript using generators
Reference
doM(comprehension: function*, reentrant?: boolean)
Do-syntax for comprehension
's algebraic type. If reentrant
is true
, uses a re-entry safe version — it's up to the user to signal when this is necessary.
Re-entrancy is necessary for Lists and other multi-valued types, where the function argument generated by doM
for chain
could be called multiple times.
doM
is syntactic sugaring for nested chain
calls:
// doM syntactic sugaring, single level of nesting
doM(function*() {
const v1 = yield expression1(...)
...
const vN = yield expressionN(...)
return expression(v1, vN)
})
// Corresponding nested chain expressions, N+1 levels of nesting
expression1(...).chain(v1 =>
...
expressionN(...).chain(vN =>
expression(v1, vN)))
Example
For some hypothetical types List
and Option
(that conform to the
Fantasy Land Specification),
you could write for example the following comprehensions:
const res1 = doM(function*() {
const x = yield List.fromArray([1, 2])
const y = yield List.fromArray([3, 4])
return List.fromArray([x + y])
}, true)
console.log(res1) //=> List { xs: [ 4, 5, 5, 6 ] }
const res2 = doM(function*() {
const x = yield Option.some(1)
const y = yield Option.some(2)
return Option.some(x + y)
})
console.log(res2) //=> Some { x: 3 }
const res3 = function() {
const xs = List.fromArray([...Array(2).keys()])
const ys = List.fromArray([...Array(2).keys()])
return doM(function*() {
const x = yield xs.chain(x => List.fromArray([x, x + 1]))
const y = yield ys.map(y => y + 1)
return List.fromArray([x * y])
}, true)
}()
console.log(res3) //=> List { xs: [ 0, 0, 1, 2, 1, 2, 2, 4 ] }