首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >StateT单模的写区间函数

StateT单模的写区间函数
EN

Stack Overflow用户
提问于 2015-09-25 08:02:01
回答 1查看 123关注 0票数 1

因此,我编写了我自己的StateT实现,因为我无法让变压器在Haste中正确编译。我想要让javascript setInterval在我的状态单元中工作。这是对setInterval的ffi电话。

代码语言:javascript
复制
jsInterval :: Int -> IO () -> IO Int
jsInterval = ffi "(function(t,f){window.setInterval(f,t);})"

无论如何,在将m传递给jsInterval之后,我都想不出它的结果。所以我试着使用IORefs

代码语言:javascript
复制
interval :: Int -> StateT s IO () -> StateT s IO Int
interval i m = StateT $ \s -> do
    ref <- newIORef Nothing
    id_ <- jsInterval i $ do
                       (_, s') <- runStateT m s
                       writeIORef ref (Just s')
    s' <- readIORef ref
    return (id_, s')

这不起作用是因为它保持了原来的状态。阅读发生在写之前。因此,我编写了一个函数,它可以在循环中轮询,直到编写了IORef,但是这个函数将永远挂起。

代码语言:javascript
复制
interval :: Int -> StateT s IO () -> StateT s IO Int
interval i m = StateT $ \s -> do
    ref <- newIORef Nothing
    id_ <- jsInterval i $ do
                       (_, s') <- runStateT m s
                       writeIORef ref (Just s')
    s' <- go ref
    return (id_, s')
  where
    go ref = do
      s <- readIORef ref
      case s of
        Nothing -> go ref
        Just s' -> return s'

有可能实现这个功能吗?我尝试为MonadEvent编写一个StateT实例,但也没有成功。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-25 09:41:32

传递给FFI‘’ed jsInterval的IO操作只是一个普通的IO操作。如果您使用runStateT实现该操作,那么您只是在运行一些“本地”StateT。与封闭式代码无关。

这是回调和monad堆栈的一个通用问题--回调(从IO(的意义上说,jsInterval是回调)在其定义中选择了一个固定的单变量,它们无法推广到其他地方可能使用的其他一元效应。

由于回调--通常情况下--可以在调用函数完成并其状态被破坏之后,在不同的线程中随时调用,包括多次调用--您可以看到,这通常是很难解决的问题。

实用的答案是,正如您已经尝试过的那样,只使用一个IORef;在封闭操作中创建IORef并让回调修改它。如果愿意,仍然可以用StateT风格编写回调--只需从IORef中提取状态并将其传递给runStateT即可。您的代码没有这样做,您只是从顶层引用参数s:您需要使用IORef,如下所示:

代码语言:javascript
复制
id_ <- jsInterval i $ do
                   current_s <- readIORef ref
                   (_, new_s) <- runStateT m current_s
                   writeIORef ref (new_s)

你不能真正使用Maybe,除非你准备好教动作m如何对付Maybe --它需要处理Nothing,所以也许你想让它具有StateT (Maybe s) IO ()类型?

第二个逻辑问题(?)使用您的代码,interval返回的interval当然不会被更改--在javascript返回其空闲循环之前不可能触发setInterval代码。

多年来,对传递回调的一般问题进行了多次讨论,请参阅:

https://mail.haskell.org/pipermail/haskell-cafe/2007-July/028501.html http://andersk.mit.edu/haskell/monad-peel/ http://blog.sigfpe.com/2011/10/quick-and-dirty-reinversion-of-control.html

等。

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

https://stackoverflow.com/questions/32777502

复制
相关文章

相似问题

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