使用reactive-banana处理相互递归的GUI小部件

时间:2012-11-04 01:41:19

标签: user-interface haskell frp reactive-banana

我正在寻找一个库来在GLFW和OpenGL之上编写GUI。我这样做是因为我对常见的UI库绑定不满意,我认为这些绑定太过于必要,而且我也想严格控制UI的外观和感觉。我想要一种定义UI的声明方法。我正在尝试使用反应性香蕉(以及临时反应性香蕉-wx)来确定它是否符合我的需求。我在定义递归小部件时遇到问题。这是我最简单的测试用例:

  • 显示计数器的文本小部件。
  • 一个增加计数器的按钮小部件。
  • 当计数器为0且处于活动状态并将计数器重置为0时,处于非活动状态的按钮小部件(因此它显示为灰色并且根本不响应输入)。

第一个和第三个小部件具有递归关系。第一个小部件直观地是从这两个按钮馈送的stepper个事件union。但是,重置按钮是计数器的fmap,然后事件流依赖于重置按钮!该怎么办?

除了这个问题,我还关注事件处理:由于我想在我的代码中处理设备输入和输入焦点而不是依赖于框架,我发现在以可伸缩的方式正确调度事件方面存在困难。理想情况下,我将定义一个data,它封装了一个小部件的层次结构,一种在元素之间安装事件回调的方法,然后编写一个遍历该数据结构的函数,以便定义设备输入处理和图形输出。我不知道如何处理事件流并将其拆分,因为事件流可以合并。

1 个答案:

答案 0 :(得分:5)

允许递归,只要它是BehaviorEvent之间的相互递归。关于Behavior s的好处是在更新时对它们进行采样将返回旧值。

例如,您的示例可以表示如下

eClick1, eClick2 :: Event t ()

bCounter :: Behavior t Int
bCounter = accumB 0 $ mconcat [eIncrement, eReset]

eIncrement = (+1)      <$ eClick1
eReset     = (const 0) <$ whenE ((> 0) <$> bCounter) eClick2

另见问题"Can reactive-banana handle cycles in the network?"


关于你的第二个问题,你似乎在寻找函数filterE及其堂兄filterApplywhenE


至于你的总体目标,我认为这是非常雄心勃勃的。从迄今为止我获得的经验来看,在我看来,绑定到现有框架与在FRP中构建“清洁状态”框架完全不同。最有可能的是,仍有一些未被发现的(但令人兴奋的!)抽象潜伏在那里。我曾经开始编写一个名为BlackBoard的应用程序,其中包含一个关于时变图的很好的抽象。

但是,如果你更关心结果而不是冒险,我会建议采用一种保守的方法:以命令式方式创建GUI工具包,并在其上加上反应性香蕉,以获得FRP的好处。

如果您只是希望任何 GUI,我目前专注于Web浏览器作为GUI。这里有一些preliminary experiments with Ji。与wxHaskell相比的主要优点是,它更易于启动和运行,任何API设计工作都将使广大受众受益。