【问题标题】:Do-notation in TypeScriptTypeScript 中的 Do-notation
【发布时间】:2017-11-15 18:10:33
【问题描述】:

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

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

【问题讨论】:

  • 您能否添加一些代码来准确显示您的意思并给我们一些可以使用的东西?
  • 我对 TypeScript 和 JavaScript 知之甚少,但也许 this 可以移植到 TypeScript?

标签: typescript functional-programming monads


【解决方案1】:

我的时间有限,但这里有一个简单的小例子,使用延续单子 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,但是你的值会卡在 Promise 中——在大多数情况下这可能很烦人。

【讨论】:

  • 如果你真的想依赖它,你会想要对它进行一些错误检查——现在它假设产生的类型有一个chain 方法。
  • 我认为生成器函数不适用于列表单子。此外它们是有状态的,你不能在高阶函数中产生,因此没有 map/reduce 等。但是,我也不知道更好的方法。但我会考虑的。
猜你喜欢
  • 2021-08-14
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
  • 2018-09-05
  • 2013-05-19
  • 2015-08-22
  • 2012-05-13
相关资源
最近更新 更多