TypeScript 中的 Do-notation

Do-notation in TypeScript

我正在尝试找出一种方法来美化 TypeScript 中的单子库。虽然 monad 本身的实现进展顺利,但它的用法看起来像熟悉的回调地狱。

我想知道是否有办法劫持 async/await 或 yield/for..of 的现有 monadic 语法糖,但我必须承认我在连接这些点时遇到了一些麻烦。是否可以在既不是 Promise 也不是 Iterable 的东西上使用这些构造,并且与由反应组件组成的延续 monad 一样不同?

我的时间有限,但这里有一个使用 continuation monad Cont 作为示例的快速小示例

// first: WITHOUT do-notation

const Cont = f => ({
  runCont: f,
  chain: g =>
    Cont(k => f (x => g (x) .runCont (k)))
})

Cont.of = x =>
  Cont(k => k (x))

const result = Cont.of (2) .chain (x =>
  Cont.of (3) .chain (y =>
    Cont.of (x + y)))

result.runCont (console.log)
// 5

现在同样的事情使用了一种do-notation——do是JS中的保留关键字,所以我将我的函数命名为run

// second: WITH do-notation

const run = g => {
  const next = x => {
    let {value, done} = g.next (x)
    return done
      ? value
      : value.chain (next)
  }
  return next (null)
}

const Cont = f => ({
  runCont: f,
  chain: g =>
    Cont(k => f (x => g (x) .runCont (k)))
})

Cont.of = x =>
  Cont(k => k (x))

const result = run (function* () {
  let x = yield Cont.of (2)
  let y = yield Cont.of (3)
  return Cont.of (x + y)
} ())

result.runCont (console.log)
// 5


警告: 可以 使用 async/await 但是你的值会卡在 Promises 中——这可能很烦人大多数情况下。