首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在JS中实现类似IO类型的MonadFix实例?

如何在JS中实现类似IO类型的MonadFix实例?
EN

Stack Overflow用户
提问于 2020-12-10 21:41:59
回答 1查看 90关注 0票数 0

我完全无法尝试将以下Haskell代码转换为Javascript:

代码语言:javascript
复制
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

,让我们按照我们的小时间旅行类比逐行走一遍:

variable.

  • Predict
  1. 创建一个空的可变值,即包含在该可变变量中的未来值。
  2. 用预测的未来值调用函数f。
  3. 将f的结果存储在变量中,从而实现了第2行所要求的预言。
  4. 返回该结果。

G 214

我所拥有的是一种特殊的Lazy类型,它处理(或者更确切地说是延迟)同步IO。但是,我想用值递归从直接递归中抽象出来:

代码语言:javascript
复制
const record = (type, o) =>
  (o[Symbol.toStringTag] = type.name || type, o);

const Lazy = lazy => record(Lazy, {get lazy() {
  delete this.lazy
  return this.lazy = lazy();
}});

// Monad

const lazyChain = mx => fm =>
  Lazy(() => fm(mx.lazy).lazy);

const lazyChain_ = fm => mx =>
  Lazy(() => fm(mx.lazy).lazy);

const lazyOf = x => Lazy(() => x);

// mfix = chain_ => fm => chain_(fm) (mfix(chain_) (fm)) ???

// MAIN

const trace = x => (console.log(x), x);
const app_ = x => f => trace(f(x));

const readLine = s => Lazy(() => window.prompt(s));

const fac = x => x === 0 ? 1 : x * fac(x - 1),
  tri = x => x === 0 ? 0 : x + tri(x - 1);

const foo = lazyChain(readLine("enter true/false")) (s => {
  return lazyOf(s === "true"
    ? fac : tri);
});

const bar = x => lazyChain(foo) (y => lazyOf(app_(x) (y)));
const main = bar(5);

console.log("effect has not yet been unleashed..");
main.lazy;

如何在Javascript中实现MonadFixMonadFix实例?

EN

回答 1

Stack Overflow用户

发布于 2020-12-11 01:26:02

您的Lazy构造有一个块的表示,它恰好形成了一个monad (正如您所写的那样,一元应用程序只是严格的函数应用程序),但是您没有IO的表示,所以实际上您只是在任何地方使用unsafePerformIO

在您的模型中,每个I/O操作只能执行一次,因此我预计,除非添加一个单独的IO包装器,其内容类似于一个runIO函数(或属性,如果您愿意),它不会与回忆录结果共享Lazy覆盖自己的行为,或者可能添加某种方式显式复制延迟操作,否则就不会像预期的那样工作。当然,mfix f只运行一次f的效果--也就是说,它用于使用效果来生成惰性/自引用的数据结构--所以这对您的目的来说可能是很好的。

除了这些警告之外,我们完全有可能为您的thunk结构表示类似于MonadFix实例的东西,但它只是fix的一个懒散版本

代码语言:javascript
复制
// 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)强制执行结果,然后立即将其再次打包,这既是额外的工作,也可能是对交错效果的渴望。您的版本实际上是let fx = fm mx in mx `seq` fx `seq` fx,可以(通过a `seq` a = a)将其简化为mx `seq` fm mx,然后mx `seq` fm mx等效于fm $! mx,即严格的函数应用程序。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65242729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档