I'm doing some research into practical aspects of FRP for UI's and I've been struggling with implementing the following functionality using reactive banana: based on the value of a selection box, a variable amount of list boxes are rendered which display some results. (I'm using WxHaskell.)
It was pretty straightforward to implement this using a bunch of prepared list boxes that are hidden and shown based on the result behavior, but this time I want it to create and destroy list boxes as needed, each list box linked to the results behavior.
So far I have the following ingredients:
- an event
eParam
which is bound to the selection box - a behavior
bResults :: Behavior t [[String]]
defined witheParam
(andstepper
) which holds all the results (lists of items per list box) - an update function
updateResultControls :: [SingleListBox ()] -> [[String]] -> IO [SingleListBox ()]
which destroys or builds the list boxes based on the results. Note that the return type is in IO.
Looking at the BarTab example, I've tried to implement the following:
- a behavior
bResultControls :: Behavior t [SingleListBox ()]
with the list boxes, defined asstepper [] eUpdateResultControls
. - an event
eUpdateResultControls :: Event t [SingleListBox ()]
that performs the UI update. This event depends on the behaviorsbResultControls
andbResults
. However, it also has to update the network and run IO, so I suspectMoment
andexecute
will be involved. This is where I got stuck.
My latest attempt is this:
rec
let
bResultControls = stepper [] eResultControls
bResultControlsUpdate = updateResultControls <$> bResultControls <*> bResults
eResultControls <- execute $ FrameworksMoment . liftIO <$> (bResultControlsUpdate <@ eParam)
But I get the following type error:
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)'
I suspect this will involve trimming some behaviors, or perhaps I'm going about this entirely the wrong way.