Javascript 如何在JS中实现类似IO类型的MonadFix实例?
我完全无法将以下Haskell代码翻译成Javascript:Javascript 如何在JS中实现类似IO类型的MonadFix实例?,javascript,haskell,monads,monadfix,Javascript,Haskell,Monads,Monadfix,我完全无法将以下Haskell代码翻译成Javascript: instance MonadFix IO where mfix f = do var <- newEmptyMVar -- 1 ans <- unsafeInterleaveIO $ takeMVar var -- 2 result <- f ans -- 3 putMVar var
instance MonadFix IO where
mfix f = do
var <- newEmptyMVar -- 1
ans <- unsafeInterleaveIO $ takeMVar var -- 2
result <- f ans -- 3
putMVar var result -- 4
return result -- 5
你的
Lazy
构造有一个thunks的表示,它恰好形成了一个monad(正如你所写的,monadic应用程序只是一个严格的函数应用程序),但是你没有IO
的表示,所以你基本上只是到处使用unsafePerformIO
在您的模型中,每个I/O操作只能执行一次,因此我希望这不会像您期望的那样工作,除非您添加一个单独的IO
包装器,其中包含runIO
函数(或属性,如果您愿意),该函数不会共享Lazy
用记录的结果覆盖自身的行为,或者,如果您添加了某种方法来显式复制延迟操作。当然,mfix f
只运行一次f
的效果,也就是说,它是用于使用效果生成惰性/自引用数据结构的,因此这对于您的目的可能是好的
撇开这些警告不谈,完全可以为thunk结构表达类似于MonadFix
实例的东西,但它只是fix
的一个懒惰版本:
// cf. Haskell ‘fix f = let ans = f ans in ans’
function lazyFix(f) {
var ans = Lazy(() => f(ans));
return ans;
}
如果你有副作用交织在这些重击中,它们会在你强迫它们时发生
我认为原始Haskell代码中的MVar
业务主要只是捕获无限循环子集的一种方便方式,它确保如果操作试图在写入值之前强制thunk,那么运行时将能够检测到线程“在MVar
操作中被无限阻塞”并提出一个错误
另外,您应该能够将
lazyChain
定义简化为fm(mx.lazy)
,因为lazy(()=>fm(mx.lazy.lazy)
强制执行结果,然后立即再次将其打包,这既是额外的工作,也可能是对交错效果的过分渴望。您的版本实际上是在mx`seq`fx`seq`fx中使用let fx=fm mx,可以将其简化(通过a`seq`a
=a
)为mx`seq`fm mx
,然后相当于fm$!mx,即严格的功能应用。该代码中的MVar
有点“皮带和吊带”。当前的实现使用unsafedupableinterleavio
,并依赖MVar
实现线程安全。。。实际上,我认为在编写时,unsafeInterleaveIO
可能不是线程安全的?我不记得了。无论如何,现在一切都很合理……是的,每个.lazy
查找都相当于unsafePerformIO
。我仍然可以从Lazy
中获益,因为它延迟了效果,使它们可组合,并且我只在应用程序的边缘运行它们。还有另一种类型Defer
w/o共享。我了解到,当你使用不纯净的代码时,“积极的”共享是一个很好的特性,b/c它有助于非幂等效应。JS实际上不计算thunk literal()=>fm(mx.lazy)。lazy
在lazy(()=>fm(mx.lazy).lazy)
,但只有在.lazy
上查找它时。如果我只有fm(mx.lazy)
那就太急切了,因为fm
会被立即调用,而不会产生mx
的效果。