unwrap的奇怪行为(purescript-signal)

时间:2017-12-30 22:35:55

标签: purescript

看一下purescript-signal示例,我看到一个常见的模式是使用纯更新函数和一个有效的 render 函数:

runSignal $ map render (foldp update initialState input)

但是如果渲染需要保持状态,该怎么办,例如因为 render 中的有效渲染操作会返回以下对 render 的调用所需的值吗?

unwrap 函数看起来像是要走的路,用这样的东西:

unwrap $ foldp render (pure initialRenderState) (foldp update initialState input)

我制作了以下代码来试用 unwrap ,但它没有像我预期的那样工作。我期待它打印从0开始的后续整数,它们之间有一秒的延迟。相反,它每秒打印的不仅是新数字,还包括所有以前的数字。

updateEff :: forall eff. Number -> Eff (console :: CONSOLE | eff) Int -> Eff (console :: CONSOLE | eff) Int
updateEff _ stateEff = do
    state <- stateEff
    log $ show state
    pure $ state + 1

main = do
    unwrap $ foldp updateEff (pure 0) (every 1000.0)

同样,这段代码只是尝试 unwrap 的一个例子,我知道这些特定的操作可以重写,例如使用纯更新功能和&#34;渲染&#34; function:runSignal $ map render(foldp update 0(每1000.0))

为什么每次都会重新打印整个数字序列?

1 个答案:

答案 0 :(得分:1)

  

为什么每次都会重新打印整个数字序列?

似乎使用foldp创建的信号可以构建越来越大的Eff值。因此,例如在第三次迭代之后,您在聚合效果中有类似的东西:

state ← do
  state ← do
    state ← pure 0
    log $ show state
    pure $ state + 1
  log $ show state
  pure $ state + 1
log $ show state
pure $ state + 1

foldp未运行您的Eff值。另一方面unwrap根据文档“(...)获取输入信号产生的每个效果并运行它(...)”Efffoldp产生的值purescript-refs信号在聚合后在最后进行评估,因此我们观察累积效应。

  

但是如果渲染需要保持状态,该怎么办,例如因为渲染中有效的渲染操作会返回以下调用渲染所需的值吗?

我不确定这是否是最好的方法,但您可以使用module Main where import Prelude import Control.Monad.Eff.Console (logShow) import Control.Monad.Eff.Ref (modifyRef, newRef, readRef) import Signal (unwrap) import Signal.Time (every) main = do s ← newRef 0 let updateEff _ = do readRef s >>= logShow modifyRef s (_ + 1) unwrap $ map updateEff $ every 1000.0 中的可变引用来保持调用之间的状态 - 这样的事情应该有效:

{{1}}