2

我有以下测试程序:

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

我正在创建一个包含两个事件的网络。eNumInts中的eShow一个事件()。每当eShow被提出,printInitial被执行。

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

所以,

  • 目的是trimB什么?
  • 是否可以转换x :: Behavior t0 a为aty :: Behavior t1 ainitial y值?xt1
4

1 回答 1

1

您的直觉是(应该是)正确trimB的:后面now应该返回 Behavior 的当前值。

但是,您的代码有一个严重的问题:它在编译另一个网络(第二个)期间使用Behavior在一个网络中创建的( )。这样做的结果是未定义的——即使类型似乎有效!对此我很抱歉。compilecompile

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


至于您的问题:trimB并且trimE仅用于更改 Behavior 的开始时间。一个网络内的事件以允许动态切换。从语义上讲,这个trimB函数甚至看起来是一个空操作,但在内部,有必要对其进行修整。

于 2014-11-21T09:55:47.600 回答