看一下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))
为什么每次都会重新打印整个数字序列?
答案 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
根据文档“(...)获取输入信号产生的每个效果并运行它(...)”Eff
由foldp
产生的值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}}