在FRP.Reactive.FieldTrip中使用MonadPlus

时间:2010-04-03 17:25:25

标签: haskell functional-programming reactive-programming

我正在通过FieldTrip适配器研究FRP。并以奇怪的帧调度和集成方式解决问题。所以现在我正在尝试构建自己的标记事件来对齐行为步进。

因此...

flipflop :: Behavior String
flipflop = stepper "none" (xflip 2) where
    xflip t0 = do
        t <- withTimeE_ (atTime t0)
        return "flip" `mplus` xflop (t+3)
    xflop t0 = do
        t <- withTimeE_ (atTime t0)
        return "flop" `mplus` xflip (t+2)
txtGeom = ((uscale2 (0.5::Float) *%) . utext . show <$>)
main = anim2 (txtGeom . pure flipflop)

问题是:

  • 为什么这个例子会导致内存泄漏?
  • 是否有安全的方法来构建事件序列,其中每个事件都根据之前的时间安排?
  • 1 个答案:

    答案 0 :(得分:1)

    看起来以这种方式加入活动似乎不起作用。试试这个:

    import FRP.Reactive
    import FRP.Reactive.FieldTrip
    import Graphics.FieldTrip
    import Control.Monad
    import Control.Applicative
    
    
    flipflop = stepper "none" $ either (const "flip") (const "flop")
                <$> eitherE (atTimes ((+2) <$> [0,5..])) (atTimes [5,10..])
    
    txtGeom = ((uscale2 (0.5::Float) *%) . utext . show <$>)
    main = anim2 (txtGeom . pure flipflop)
    

    不幸的是,这个版本仍有空间泄漏,但它要小得多。运行大约一分钟后,总RAM使用率约为9.7MB。

    还有一个flipFlop函数可以创建Behavior Bool。这适用于触发器,但我没有看到在前两秒添加“无”的干净方法。

    我也试过这个

    flipflop = stepper "none" $ (const "flip" <$> (atTimes ((+2) <$> [0,5..])))
                                `mplus` (const "flop" <$> atTimes [5,10..])
    

    似乎与第一个版本完全相同。

    当然,这对于以您询问的方式进行动态调度没有太大作用。不幸的是,我不相信这个用例在Reactive中有用。

    我非常钦佩那些产生Reactive的作品,我想要它,但是理由似乎非常棘手。来自邮件列表的This thread是一个似乎常见的问题(和解决方案!)的一个例子。此外,“unamb”库(它是Reactive的大部分内容)暴露了GHC线程中的一些非常微妙的错误,这些错误对结果造成了严重破坏,直到它们被固定在ghc-6.12附近。虽然这绝不是Conal或其他Reactive贡献者的错,但它使得使用该框架变得更加困难,特别是对于早期的GHC而言。

    您可以尝试其他一些FRP包。 Yampa有一个很好的实现,我听说Elerea相对来说比较简单,并且有一个很好的demo application