Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.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中实现带分隔符的延续单子-`reset`幂等性错误_Javascript_Functional Programming_Monads_Continuations_Delimited Continuations - Fatal编程技术网

在JavaScript中实现带分隔符的延续单子-`reset`幂等性错误

在JavaScript中实现带分隔符的延续单子-`reset`幂等性错误,javascript,functional-programming,monads,continuations,delimited-continuations,Javascript,Functional Programming,Monads,Continuations,Delimited Continuations,这是一个艰难的过程。我一直在尝试编写各种单子,这是唯一一个我在任何地方都找不到简洁示例的单子,因此我尝试编写自己的shift和reset,使用(JS)和(Agda)作为参考。特别是, shift : ∀ {r o i j a} → ((a → DCont i i o) → DCont r j j) → DCont r o a shift f = λ k → f (λ x → λ k′ → k′ (k x)) id reset : ∀ {r i a} → D

这是一个艰难的过程。我一直在尝试编写各种单子,这是唯一一个我在任何地方都找不到简洁示例的单子,因此我尝试编写自己的
shift
reset
,使用(JS)和(Agda)作为参考。特别是,

shift        : ∀ {r o i j a} → ((a → DCont i i o) → DCont r j j) → DCont r o a
shift f      = λ k → f (λ x → λ k′ → k′ (k x)) id

reset        : ∀ {r i a} → DCont a i i → DCont r r a
reset a      = λ k → k (a id)
我遇到的问题是,当我通过多个
reset
s测试是否中止时,我的实现失败:

//分隔的连续单子
类DCont{
(x){returnnewdcont(resolve=>resolve(x))}的静态
构造函数(run){this.run=run}
chain(fn){返回新的DCont(resolve=>this.run(x=>fn(x.run(resolve))}
map(fn){返回this.chain(x=>DCont.of(fn(x))}
ap(dc){返回这个.chain(fn=>dc.map(fn))}
shift(subc){returnnewdcont(resolve=>subc(dc=>dc.map(resolve)).run(x=>x))}
静态重置(comp){return DCont.of(comp(DCont.of(x=>x)).run(x=>x))}
}
//设置测试
设sqr=x=>x*x,
单次移位复位=DCont
.reset(p=>p
.shift(k=>k(k(第(5)部分的数据)))
.map(x=>x+1))
.map(x=>x*2),
多重移位中止=DCont
.reset(p=>DCont
.reset(p2=>p
.shift(k=>DCont.of(5))
.map(x=>1000))
.map(x=>x+1))
.map(x=>x*2),
liftM2=(f,m1,m2)=>m1.链(x=>m2.映射(y=>f(x,y)),
listOf=(m1,m2)=>liftM2((x,y)=>[x,y],m1,m2),
加法=(x,y)=>x+y,
多重移位输入复位=DCont
.reset(p=>liftM2(添加、,
p、 移位(k=>listOf(k(第1部分的数据)),k(第2部分的数据)),
p、 移位(k=>listOf(k(DCont.of(10)),k(DCont.of(20)))
));
//运行测试
console.log(单次移位复位运行(sqr))//预期196=((5+1+1)*2)^2
console.log(multi\u shift\u abort.run(sqr))//预期100=(5*2)^2
console.log(multi\u-shift\u-in\u-reset.run(x=>x))//预期[[11,21],[12,22]
问题出在这里

  • 分隔连续性的Adga实现不考虑区域
  • 分隔的continuations的JavaScript实现确实考虑了区域
  • 您试图将分隔的continuations的Adga实现与JavaScript测试套件一起使用,因此您没有走多远

    不带区域的分隔连续体 考虑以下程序

    example=do
    x^2)
    
    使用不带区域的分隔连续时,每个
    移位
    都被分隔到最近的
    重置
    。因此,在上述程序中,结果为
    ((5+1)*2)^2
    ,其计算结果为
    144

    您的
    shift
    reset
    实现基于Agda实现。因此,它的计算结果为
    144
    。还有一个没有区域的分隔连续体,更简单

    带区域的分隔连续体

    现在,使用与区域分隔的延续来考虑同一个程序。

    example=do
    x do
    
    x幂等性问题通常发生在严格的环境中。Agda的评估顺序似乎正常。我想问题在于
    reset
    的严格性。不幸的是,我没有时间钻研细节……啊,现在一切顺利!我链接到的参考JS使用了与您链接的论文相同的
    newPrompt
    pushPrompt
    withSubCont
    pushSubCont
    原语(我已经遇到过),但我没有意识到复杂性差异的原因。在这种情况下,我自己的
    shift
    方法应该是静态的。当我找不到一种方法将
    这个函数干净地合并到一起时,我可能意识到出了什么问题。运行
    到函数中!另外,
    shift
    的Haskell实现需要在
    标识
    monad上运行一个转换器,因此对于给定的范围,我更喜欢Agda版本。@Aadit仍然应该对
    重置a=λk进行自适应→ k(a id)
    对于严格评估的环境,使用构造函数而不是
    (aka
    return
    ),因为后者是严格的?类似于
    const reset=cont=>cont(k=>k(cont.run(id)))
    @scriptum Yes,如果您想将计算推迟到实际提供延续之前。