Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/429.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 从单子的角度来看,承诺的递归连接意味着什么?_Javascript_Haskell_Promise_Monads_Es6 Promise - Fatal编程技术网

Javascript 从单子的角度来看,承诺的递归连接意味着什么?

Javascript 从单子的角度来看,承诺的递归连接意味着什么?,javascript,haskell,promise,monads,es6-promise,Javascript,Haskell,Promise,Monads,Es6 Promise,我知道Javascript的承诺在技术上既不是Haskell意义上的函子也不是单子,因为(除其他外) 它们包括一个bind操作,当传入纯函数时,该操作返回到map(因此具有不明确的类型) Promise构造函数和resolve(akareturn)递归地连接嵌套的承诺 通过始终提供类型正确的函数a->Promise b,可以轻松绕过第一个问题 第二个问题显然违反了参数多态函数的参数特性,即不能构造m(ma)结构。但是,在承诺/异步计算的上下文中,这种结构意味着什么?我想不出Promise(P

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

  • 它们包括一个
    bind
    操作,当传入纯函数时,该操作返回到
    map
    (因此具有不明确的类型)
  • Promise
    构造函数和
    resolve
    (aka
    return
    )递归地连接嵌套的承诺
通过始终提供类型正确的函数
a->Promise b
,可以轻松绕过第一个问题

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

如果我们非常务实(这也是我们在编写Javascript时应该做到的),那么如果我们考虑到边缘情况,我们难道不能声称
承诺
是Javascript中的单子吗

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

或者不使用
then
作为monad的
bind
操作,而是使用一些类型正确的操作。是一个功能性的promise库,提供了
map
chain
方法,这些方法实现了代数类型的

第二个问题也可以用相同的方法绕过,不使用
resolve
,而是使用
fulfill
,将
方法的静态
作为单位函数

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

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

但是,类似类型的一个很好的例子是:它返回解析为
响应的承诺
对象,该对象再次“包含”解析为响应主体的承诺

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

  • 可能在不同的时间完成,添加“中间步骤”
  • 可能会以不同的原因拒绝—例如,外部表示网络问题,而内部表示解析问题
请注意,
Promise
类型应该有第二个类型变量作为拒绝原因,类似于
。两级
Promise err1(Promise err2 A)
Promise err A
有很大不同

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

然而,您还没有提到最大的问题:它们是可变的。当我们考虑执行顺序时,从未决状态到固定状态的转换是一个副作用,它破坏了参考透明性,当然,我们通常的承诺用例包含很多不被允诺类型所模拟的IO。
Promise.delay(50).then(() => Promise.delay(50))
// does something different than
const a = Promise.delay(50); a.then(() => a)
应用单子定律很有趣,偶尔也有用,但我们确实需要很多实用主义

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

,以任何其他方式

  • 它们包括一个绑定操作,当传入纯函数(因此具有不明确的类型)时,该操作返回到映射
JS native promises没有提供
bind
操作符

  • 承诺构造函数和resolve(aka return)都递归地连接嵌套承诺
我想你的意思是展开“thenables”,即调用存储在
then
prop下的函数,只要有这样的函数

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

这与
map
不同,例如当
map(f)
用于
f=x=>{then:a=>a}

第二个问题显然违反了参数多态函数的参数特性,即不能构造
m(ma)
结构

的确如此

但是,在承诺/异步计算的上下文中,这种结构意味着什么?我想不出
Promise(Promise a)
有什么意义的语义,其中
Promise
是单子。那么我们会失去什么呢?递归连接的含义是什么

您需要允许存储任意值。承诺不允许存储不可拆封的信封,这就是问题所在。所以您需要更改对象和方法的语义。允许对象在不更改的情况下存储可伸缩性,并实现一次精确展开(或连接)可伸缩性的
.bind
aka
.chain
,无需递归

这就是promise类对象和基于回调(又名连续传递样式)函数的作用


如果我们非常务实(这也是我们在编写Javascript时应该做到的),那么如果我们考虑到边缘情况,我们难道不能声称承诺是Javascript中的单子吗

编写安全、简洁和可组合的代码是务实的。冒着通过泄漏的抽象引入细微缺陷的风险,可能会使关键软件崩溃并产生深远的后果,这是不可能的。 每个边缘案例都是此类风险的潜在来源

在这方面,声称
Promise
是单子除了不正确之外,弊大于利。这是有害的,因为您无法安全地应用一元变换