atz*_*tze 6 haskell frp reactive-programming reactive-banana
我目前正在使用reactive-banana和reactive-banana-wx软件包重新设计一个遗留的wxHaskell.但是,为了避免动态网络构建(我遇到了MVar上的线程块),我现在通过预构建一组固定的wxHaskell小部件来模仿这一点,我根据需要设置了可见性.可见性由sink函数a设置Behavior.但是,wxHaskell要求在通过适当修改所有这些小部件之后,需要sink随后更改保存这些小部件的面板的布局.这意味着sink-ing实际上应该是网络的一部分,因此它是一个可以触发并等待布局更改的事件.就目前而言,一个sink将您带出事件网络,在sink操作完成后无法触发事件.我确实试图适应sink这样的事情:
sink' :: Frameworks t =>
w -> [Prop' t w] -> Moment t (Event t ())
sink' widget props = do
es <- mapM sink1 props
return $ unions es
where
sink1 (attr :== b) = do
x <- initial b
liftIOLater $ set widget [attr := x]
e <- changes b
return $ (\x -> unsafePerformIO $ set widget [attr := x]) <$> e
Run Code Online (Sandbox Code Playgroud)
但是,unsafePerformIO没有得到执行.如何实现所需的行为,即允许(wxHaskell)IO通过Event?等待?
基本上,您似乎想确保 中的 IO 操作reactimate按一定顺序执行?也就是说,您要确保布局是在之后设置的在设置小部件属性
有几种方法可以指定顺序:
\n\nunion,unionWith和/或collect确定同时事件的顺序。reactimate使用按照它们在 monad 中出现的顺序执行的事实Moment。(尽管严格来说,当您使用observeE。)根据您的具体情况,可以按如下方式应用这些想法。
\n\n对于1,您可以创建一个包含IO操作的事件,并稍后将其与布局结合起来
\n\nsink\' :: Frameworks t =>\n w -> [Prop\' t w] -> Moment t (Event t (IO ()))\nsink\' widget props = do\n es <- mapM sink1 props\n return $ foldr1 (unionWith (>>)) es\n where\n sink1 (attr :== b) = do\n x <- initial b\n liftIOLater $ set widget [attr := x]\n e <- changes b\n return $ (\\x -> set widget [attr := x]) <$> e\nRun Code Online (Sandbox Code Playgroud)\n\n对于2,你可以简单地使用普通的sink函数,并确保布局是最后设置的。
do\n sink widget1 [ visible :== bBool ]\n sink window1 [ layout :== bLayout ]\nRun Code Online (Sandbox Code Playgroud)\n\n的排序sinkmonad 中函数
另请注意,从reactive-banana 0.7 开始,您可以使用动态事件切换来对一组可变的小部件进行建模。请参阅BarTab.hs 示例进行演示。此示例还设置了布局。
\n\n您表示在使用动态网络时会遇到 MVar 块。这可能是因为您创建小部件的方式会触发网络中的另一个事件。不幸的是,这在语义上是不合理的 \xe2\x80\x94 它对应于取决于其自身未来版本的值 \xe2\x80\x94 并且程序通过陷入最低点来响应。
\n