我正在研究用于UI的FRP的实际方面,我一直在努力使用反应香蕉实现以下功能:基于选择框的值,呈现可变数量的列表框,显示一些结果。 (我正在使用WxHaskell。)
使用一堆基于结果行为隐藏和显示的准备列表框来实现这一点非常简单,但这次我希望它根据需要创建和销毁列表框,每个列表框都链接到结果行为。
到目前为止,我有以下成分:
eParam
bResults :: Behavior t [[String]]
(和eParam
)定义的行为stepper
,其中包含所有结果(每个列表框中的项目列表)updateResultControls :: [SingleListBox ()] -> [[String]] -> IO [SingleListBox ()]
,它根据结果销毁或构建列表框。请注意,返回类型位于IO。查看BarTab示例,我尝试实现以下内容:
bResultControls :: Behavior t [SingleListBox ()]
,定义为stepper [] eUpdateResultControls
。 eUpdateResultControls :: Event t [SingleListBox ()]
。此事件取决于行为bResultControls
和bResults
。但是,它还必须更新网络并运行IO,因此我怀疑将涉及Moment
和execute
。这就是我被卡住的地方。我最近的尝试是:
rec
let
bResultControls = stepper [] eResultControls
bResultControlsUpdate = updateResultControls <$> bResultControls <*> bResults
eResultControls <- execute $ FrameworksMoment . liftIO <$> (bResultControlsUpdate <@ eParam)
但是我收到以下类型错误:
Couldn't match type `m0 [SingleListBox ()]'
with `forall t1. Frameworks t1 => Moment t1 [SingleListBox ()]'
Expected type: IO [SingleListBox ()]
-> forall t. Frameworks t => Moment t [SingleListBox ()]
Actual type: IO [SingleListBox ()] -> m0 [SingleListBox ()]
In the second argument of `(.)', namely `liftIO'
In the first argument of `(<$>)', namely
`FrameworksMoment . liftIO'
In the second argument of `($)', namely
`FrameworksMoment . liftIO <$> (bResultControlsUpdate <@ eParam)'
我怀疑这会涉及修剪某些行为,或者我可能完全以错误的方式解决这个问题。
答案 0 :(得分:2)
经过一些阅读和实验后,我得到了一些仔细的修剪和重构(正如海因里希所暗示的那样):
networkDescription :: forall t. Frameworks t => Moment t ()
networkDescription = do
eParam <- choiceSelection cParam
let bResults = results <$> stepper x eParam
bResults_ <- trimB bResults
rec
let
bResultControls = stepper [] eResultControls
mkResultControls :: [SingleListBox ()] -> [[String]] -> FrameworksMoment [SingleListBox ()]
mkResultControls cs rs = FrameworksMoment $ do
slResults <- liftIO $ updateResultControls cs rs
bResults <- now bResults_
sequence_ [sink sl [items :== (!! i) <$> bResults] | sl <- slResults | i <- [0..]]
liftIO $ do
let n = length rs
set f [clientSize := sz (150 * n) 200]
set pResults [layout := fill $ boxed "results" $ row n (map (fill . widget) slResults)]
refit f
return slResults
eResultControls <- execute $ (mkResultControls <$> stepper [] eResultControls <*> bResults) <@ eParam
return ()
(现在只是在行为更新之前事件发生的地方出现了一个小错误,但应该很容易修复。)