Dear list,

as you probably know, I'm the author of the reactive-banana package, 
which is a library for functional reactive programming (FRP) which can 
be used with wxHaskell. As such, I would like to propose a few changes 
to wxHaskell which are informed by FRP. Of course, while my primary aim 
is to gain better interoperability with my library, I think and hope 
that my proposed changes are of independent benefit.

Today, I would like discuss *composable events* and event handlers.

In wxHaskell, event handlers are currently set with the  on  combinator.

     set button [ on command := doSomething ]

Unfortunately, this approach has several problems that don't make it 
very composable:

1. Currently, setting an event handler will also *remove* any previous 
event handler.
2. The event handler may have have several curried parameters, or even none.

I have found that the most composable approach to events is the 
following type

     type Event a = AddHandler a
     newtype AddHandler a = AddHandler { addHandler :: (a -> IO ()) -> 
IO (IO ()) }

Example usage

     doSometing :: () -> IO ()
     removeSomething <- addHandler (on command button) doSomething

The idea is that  Event a  represents an event that carries data of type 
  a . If the event does not carry any data, then  a = () . The 
addHandler  function registers an additional event handler with the 
event, while keeping the old handlers intact. The return value of 
addHandler  can be used to remove the event handler again if desired. 
(This is how GTK does it, by the way.)

With this type, we can easily define new events from old ones, for instance

     instance Functor AddHandler where
         fmap f e = AddHandler $ \g -> addHandler e (g . f)

     filterJust :: AddHandler (Maybe a) -> AddHandler a
     filterJust e = AddHandler $ \g -> addHandler e (maybe (return ()) g)

     -- mouse click event
     click :: AddHandler Point
     click = filterJust . fmap matchClick $ mouse
         matchClick (MouseLeftDown pt _) = Just pt
         matchClick _                    = Nothing

Note that this only works well if the event data always given as a 
single type, not multiple curried arguments.

I think this is very pleasant. In particular, it cleans up the confusion 
about the current crop of write-only events like  click  and  motion . 
It also looks a bit like FRP, though it is not powerful emough to become 
"true" FRP for reasons I don't want to go into right now.

The main drawback of the  AddHandler  approach is that we cannot keep 
the current syntax

   set button [ on click := .. ]

since setting an event handler rightfully implies that the old event 
handlers are removed. I'm somewhat undecided about possible solutions, 
but we could introduce a new assignment symbol

   set button [ on click :+ .. ]

that only works on events.

What do you think?

Best regards,
Heinrich Apfelmus


Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
wxhaskell-devel mailing list

Reply via email to