我有以下测试程序:
{-# LANGUAGE RankNTypes #-}
module Main where
import Reactive.Banana
import Reactive.Banana.Frameworks
import Reactive.Banana.Switch
import Data.IORef
import Control.Monad
main = do
fShowRef <- newIORef (const (return ()))
fNumRef <- newIORef (const (return ()))
let
netDesc :: forall t. Frameworks t => Moment t ()
netDesc = do
(eNum, fNum) <- newEvent
(eShow, fShow) <- newEvent
liftIO (writeIORef fShowRef fShow)
liftIO (writeIORef fNumRef fNum)
let beh = stepper 0 eNum
behTrimmed <- trimB beh
reactimate (printInitial behTrimmed <$ eShow)
actuate =<< compile netDesc
fNum <- readIORef fNumRef
fNum 1
fShow <- readIORef fShowRef
fShow ()
printInitial :: AnyMoment Behavior Int -> IO ()
printInitial beh = do
let
netDesc :: forall t. Frameworks t => Moment t ()
netDesc = do
behNow <- now beh
initVal <- initial behNow
liftIO (print initVal)
-- compiling is enough, I just want to see the initial value
void (compile netDesc)
我希望打印
1
但打印
0
我正在创建一个包含两个事件的网络。 eNum
是Int
的事件,eShow
()
之一。每当提出eShow
时,都会执行printInitial
。
printInitial
打印行为trimB (stepper 0 eNum)
的初始值。我认为trimB
后跟now
会丢弃包含它的网络描述编译点之前的历史记录。这意味着每次引发eShow
时,都会显示一个新行为,此时此值为beh
。显然,事实并非如此。
所以,
trimB
的目的是什么?x :: Behavior t0 a
转换为y :: Behavior t1 a
,initial y
是x
t1
的价值?答案 0 :(得分:1)
你的直觉是(应该是)正确的:trimB
后跟now
应该返回行为的当前值。
但是,您的代码存在严重问题:在编译另一个网络期间,它使用在一个网络(Behavior
)中创建的compile
(第二个{{1} })。结果是未定义 - 即使类型似乎有效!对不起,我很抱歉。
我已经考虑了一段时间,并希望没有人会尝试这种组合。原则上,可以通过类型系统禁止这种情况,不幸的是,这将意味着第二个幻像参数,我不想进一步增加符号负担,所以我把它留在&#34 ;请不要这样做&#34;合同。
至于您的问题:compile
和trimB
仅用于更改行为的开始时间。一个网络内的事件允许动态切换。在语义上,trimE
函数甚至似乎是无操作,但在内部,有必要修剪它。