gpt4 book ai didi

haskell - Reactor-banana-wx `sink` 不会生成启用后接收器处理的事件

转载 作者:行者123 更新时间:2023-12-02 16:27:40 24 4
gpt4 key购买 nike

我目前正在使用reactive-banana 和reactive-banana-wx 包重新设计一个遗留的wxHaskell。然而,为了避免动态网络构建(我在 MVar 上遇到了线程 block ),我现在通过预构建一组固定的 wxHaskell 小部件来模仿这一点,我根据需要设置了这些小部件的可见性。可见性由采用Behaviorsink 函数设置。然而,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?

最佳答案

基本上,您似乎想要确保reactimate中的IO操作按照一定的顺序执行?也就是说,您需要确保在设置小部件属性之后设置布局。

有几种方法可以指定顺序:

  1. 使用 unionunionWith 和/或 collect 确定同时事件的顺序。
  2. 利用以下事实: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 block 。这可能是因为您创建小部件的方式会触发网络中的另一个事件。不幸的是,这在语义上是不合理的——它对应于取决于自身 future 版本的值——并且程序的响应是跌入谷底。

关于haskell - Reactor-banana-wx `sink` 不会生成启用后接收器处理的事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13580121/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com