修剪行为的初始值是多少

时间:2014-11-20 22:37:20

标签: haskell reactive-banana

我有以下测试程序:

{-# 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

我正在创建一个包含两个事件的网络。 eNumInt的事件,eShow ()之一。每当提出eShow时,都会执行printInitial

printInitial打印行为trimB (stepper 0 eNum)的初始值。我认为trimB后跟now会丢弃包含它的网络描述编译点之前的历史记录。这意味着每次引发eShow时,都会显示一个新行为,此时此值为beh。显然,事实并非如此。

所以,

  • trimB的目的是什么?
  • 是否可以将x :: Behavior t0 a转换为y :: Behavior t1 ainitial yx t1的价值?

1 个答案:

答案 0 :(得分:1)

你的直觉是(应该是)正确的:trimB后跟now应该返回行为的当前值。

但是,您的代码存在严重问题:在编译另一个网络期间,它使用在一个网络(Behavior)中创建的compile(第二个{{1} })。结果是未定义 - 即使类型似乎有效!对不起,我很抱歉。

我已经考虑了一段时间,并希望没有人会尝试这种组合。原则上,可以通过类型系统禁止这种情况,不幸的是,这将意味着第二个幻像参数,我不想进一步增加符号负担,所以我把它留在&#34 ;请不要这样做&#34;合同。


至于您的问题:compiletrimB仅用于更改行为的开始时间。一个网络内的事件允许动态切换。在语义上,trimE函数甚至似乎是无操作,但在内部,有必要修剪它。