I'm currently trying to get to know FRP through Heinrich Apfelmus' reactive-banana, which seems to be a quite well documented and simple library, compared to the other ones I've looked at.
However, I can't wrap my head around the AddHandler type. Let's say I want to use GLFW to get mouse button clicks so that I have something like eMouseButton :: Event (). Looking at the examples, it seems that I'd somehow have to use fromAddHandler, but I have no idea how to assemble that AddHandler argument. I think I'll have to use newAddHandler somehow, but how?
I guess an example of how to connect reactive-banana to something other than wx would help a lot.
newAddHandler is used like this:
do (addHandler, fire) <- newAddHandler
...
addHandler is the AddHandler to pass to reactive-banana, and fire is a function of type a -> IO () (where a is your event type) that triggers the event.
For instance, you would likely install fire as the callback to GLFW's mouse-button event, like so:
registerMouseButton :: IO (Event MouseButton)
registerMouseButton = do
(addHandler, fire) <- newAddHandler
setMouseButtonCallback $ \button _ -> fire button
fromAddHandler addHandler
(I'm not experienced with GLFW, so I'm not sure what the second argument to setMouseButtonCallback's callback is — if it's important, you'll need to amend this implementation appropriately.)
An AddHandler is just a function which takes a callback — a -> IO () — and registers it for the event in question; it then returns (from within IO) an IO () action used to deregister this handler, making the complete definition of AddHandler read as follows:
type AddHandler a = (a -> IO ()) -> IO (IO ())
So where does newAddHandler come in? Simple: newAddHandler maintains a list of handlers for an event, and activates them when fire x is executed.
You don't need newAddHandler if, like GTK+ and many other common toolkits, your toolkit already has facilities to register and deregister multiple event handlers; if it does, you should write your own implementation of an AddHandler. But if all it supports is a single callback, you should use newAddHandler.
Note that you never need to expose AddHandlers to the FRP-using code itself; they're just internal glue used to create Events from external inputs.
来源:https://stackoverflow.com/questions/8631816/reactive-banana-how-to-create-an-addhandler