在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]
问题出在这里
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)
对于严格评估的环境,使用构造函数而不是的(akareturn
),因为后者是严格的?类似于const reset=cont=>cont(k=>k(cont.run(id)))
@scriptum Yes,如果您想将计算推迟到实际提供延续之前。