我有一个行为,我想根据事件的发生和行为的当前值来更改其值。在下面的示例中,我有两个计数器,它们根据布尔行为是 True 还是 False 进行更新。事实上,这段代码崩溃了<<loop>>
例外,但我不确定如何重组它以使其工作或如何解决这个问题。
{-# LANGUAGE ScopedTypeVariables #-}
import Reactive.Banana
import Reactive.Banana.Frameworks
import Control.Arrow
import Control.Concurrent
import Control.Monad
import Control.Monad.Fix
counter :: Bool -> Event t Int -> Behavior t Bool -> (Behavior t Int, Event t (Bool -> Bool))
counter b input active = (result, whenE ((b/=) <$> active) (fmap (const not) input))
where result = accumB 0 (fmap (+) evt')
evt' = whenE ((b==) <$> active) input
alternater :: Event t Int -> Behavior t Bool -> (Behavior t (Bool, (Int, Int)), Event t (Bool -> Bool))
alternater input active = ((,) <$> active <*> ((,) <$> fst t1 <*> fst t2), snd t1 `union` snd t2)
where t1 = counter True input active
t2 = counter False input active
main :: IO ()
main = do
(inputHandler, fireInput) <- newAddHandler
let network :: forall t . Frameworks t => Moment t ()
network = do
eInput <- fromAddHandler inputHandler
let ui :: Behavior t (Bool, (Int, Int)) -> Moment t (Behavior t (Bool, (Int, Int)))
ui b = do
let (behavior, evt) = alternater eInput (fst <$> b)
return $ stepper id (fmap (***id) evt) <*> behavior
output <- changes =<< mfix ui
reactimate $ putStrLn . show <$> output
forkIO $ actuate =<< compile network
forever $ getLine >>= fireInput . read
例外是正确的,您直接根据行为本身定义行为。
alternater .. active = (.. <$> active <*> .. , ..)
ui b = do
let (behavior, ..) = alternater .. (.. <$> b)
return $ .. <*> behavior
... mfix ui
此代码表示结果行为的当前值ui
将以循环方式依赖于自身。
递归总是需要一点延迟才能被明确定义。最方便的方法是在事件和使用以下命令构建的行为之间使用相互递归stepper
or accumB
。也可以看看这个答案 https://stackoverflow.com/a/7852344/403805.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)