-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
72 lines (63 loc) · 1.97 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/** @module */
"use strict"
const ctrl = require("./lib/ctrl")
const Monad = require("./lib/monad")
const { Maybe, Just, Nothing } = require("./lib/maybe")
const { Either, Left, Right } = require("./lib/either")
const NodeContinuationMonad = require("./lib/node-continuation")
const PromiseMonad = require("./lib/promise")
const { unwrap, wrap } = require("./lib/utils")
const { State, get, put, modify } = require("./lib/state")
let id = 0
/**
* @function do_ Haskell's do
*/
function do_(doG, cb, stack=[], data={}) {
const doBlock = ctrl(doG(stack), stack, id)
if (!doBlock._id) doBlock._id = id++
if (stack.length === 0) {
stack.push(Object.assign({}, { data }, { doBlock }))
const { value, done } = doBlock.next()
if (done)
return cb(value)
return (function inner(stack, args) {
const {value, done} = args,
{ doBlock }= stack[stack.length - 1]
if (!done) {
const received = unwrap(value, stack.length)
if (received instanceof Monad)
return received.join(stack, inner.bind(null, stack))
else if (received instanceof Promise)
return PromiseMonad.join(stack, received, inner.bind(null, stack))
else if (received instanceof Function)
return NodeContinuationMonad.join(stack, received, inner.bind(null, stack))
// here I should deal with return values (which should by of type Monad)
} else if (stack.length <= 1) {
const returnValue = unwrap(value, stack.length - 1)
cb(returnValue)
}
})(stack, {value, done})
} else {
return (function* wrapper(stack) {
stack.push({ doBlock })
let result = yield* doBlock
stack.pop()
return result
})(stack)
}
}
function doP(gen, data={}) {
return new Promise((resolve, reject) => {
do_(gen, resolve, [], data)
})
}
module.exports = {
do: do_,
doP,
Maybe, Nothing, Just,
NodeContinuationMonad,
PromiseMonad,
Monad,
Either, Left, Right,
State, get, put, modify,
}