我目前正在使用reactive-banana和reactive-banana-wx包重新设计一段遗留的wxHaskell。但是,为了避免动态网络构造(我在MVar上遇到了线程块),我现在通过预先构造一组固定的wxHaskell小部件来模拟这种情况,我根据需要设置了这些小部件的可见性。可见性是由接受Behavior的sink函数设置的。但是,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但是,unsafePerformIO没有被执行。如何实现所需的行为,即允许通过Event等待(wxHaskell) IO
发布于 2012-11-28 00:46:46
基本上,您似乎希望确保reactimate中的IO操作按特定顺序执行?也就是说,您希望确保在设置小部件属性之后设置布局。
有几种方法可以指定顺序:
union、unionWith和/或collect来确定并发事件的顺序。reactimate按照它们在Moment monad中出现的顺序执行。(尽管严格来说,当您使用动态事件切换中的observeE组合器时,情况就不再是这样了。)在您的特定情况下,可以按如下方式应用这些想法。
对于1,您可以创建一个包含IO操作的事件,并在以后将其与布局相结合
sink' :: Frameworks t =>
w -> [Prop' t w] -> Moment t (Event t (IO ()))
sink' widget props = do
es <- mapM sink1 props
return $ foldr1 (unionWith (>>)) es
where
sink1 (attr :== b) = do
x <- initial b
liftIOLater $ set widget [attr := x]
e <- changes b
return $ (\x -> set widget [attr := x]) <$> e对于2,您可以简单地使用普通的sink函数,并确保布局是最后设置的。
do
sink widget1 [ visible :== bBool ]
sink window1 [ layout :== bLayout ]monad中sink函数的排序保证了布局是最后设置的。
还要注意,从reactive banana 0.7开始,您可以使用动态事件切换来对一组可变的小部件进行建模。有关演示,请参阅BarTab.hs example。此示例还设置布局。
您指出在使用动态网络时会遇到MVar块。这可能是因为您创建小部件的方式会触发网络中的另一个事件。不幸的是,这在语义上是不合理的-它对应于取决于自身未来版本的值-程序的反应是陷入谷底。
https://stackoverflow.com/questions/13580121
复制相似问题