以 Monad 形式递归连接 Promise 有何含义?

5 javascript monads haskell promise es6-promise

我知道 Javascript 的承诺在技术上既不是 Haskell 意义上的函子也不是 monad,因为(除其他外)

  • 它们包含一个bind回退到map传入纯函数时的操作(因此具有不明确的类型)
  • 构造Promise函数和resolve(又名return)递归地连接嵌套的 Promise

通过始终提供具有正确类型的函数,可以轻松绕过第一个问题a -> Promise b

第二个问题显然违反了参数多态函数的参数性特征,即无法构造结构m (m a)。但是这个结构在承诺/异步计算的上下文中意味着什么?我想不出Promise (Promise a), wherePromise是 monad 的有意义的语义。那么我们会失去什么呢?递归连接的含义是什么?

假设我们非常务实(这就是我们在编写 Javascript 时应该做到的),Promise如果我们考虑到边缘情况,我们不能声称 a 是 Javascript 中的 monad 吗?

Ber*_*rgi 5

通过始终提供具有正确类型的函数,可以轻松绕过第一个问题a -> Promise a

或者不使用monad 的操作,而是使用一些类型正确的操作thenCreed是一个功能性的 Promise 库,它提供了实现代数类型的Fantasy-land规范的方法。bindmapchain

第二个问题也可以通过相同的方法来绕过,即不使用resolve而是fulfill使用静态of方法作为单元函数。

但是这个结构在承诺/异步计算的上下文中意味着什么?

这是对价值的承诺。并非每个可构造类型都需要“有意义”或“有用”:-)

然而, Fetch API提供了一个类似类型的好例子:它返回一个解析为Response对象的 Promise,该对象又“包含”一个解析为响应正文的 Promise。

因此 aPromise (Promise a)可能只有一个成功结果值,也可以通过 a 访问Promise a,但是两层承诺

  • 可能在不同时间完成,添加“中间步骤”
  • 可能会因不同原因而拒绝 - 例如,外部代表网络问题,而内部代表解析问题

请注意,出于拒绝原因,该Promise类型应该有第二个类型变量,类似于Either. 两级Promise err1 (Promise err2 a)Promise err a.

我知道 Javascript 的承诺在技术上既不是 Haskell 意义上的函子也不是 monad

然而,您还没有提到最大的问题:它们是可变的。如果我们考虑执行顺序,从挂起状态到已解决状态的转换是一个副作用,它会破坏引用透明度,当然,我们通常的 Promise 用例涉及大量根本不是由 Promise 类型建模的 IO。

Promise.delay(50).then(() => Promise.delay(50))
// does something different than
const a = Promise.delay(50); a.then(() => a)
Run Code Online (Sandbox Code Playgroud)

应用单子定律很有趣,有时也很有用,但我们确实需要大量的实用主义。