On Thu, Jun 14, 2012 at 12:15 PM, Corentin Dupont <[email protected] > wrote:
> Hi folks, > I'm trying to make a simple event driven engine. It simply consists of two > functions: > - "addEvent", where you pass the event name with a callback, > - "triggerEvent" where you pass the event name with the data. > the data shall be passed to the callback of the corresponding event. > > I have trouble making it correctly typed. > Here is my try: > * > type Player = Int --dummy types for the example > type Rule = Int > data EventEnum = NewPlayer | NewRule deriving Eq > data Data = P Player | R Rule > data Handler = H (Data -> IO ()) > > addEvent :: EventEnum -> Handler -> [(EventEnum, Handler)] -> [(EventEnum, > Handler)] > addEvent e h es = (e,h):es > > triggerEvent :: EventEnum -> Data -> [(EventEnum, Handler)] -> IO () > triggerEvent e d es = do > let r = lookup e es > case r of > Nothing -> return () > Just (H h) -> h d* > > The trouble is that I want the user to be only able to add an event that > is compatible with its handler: > For example the event NewPlayer should have a handler of type Player -> IO > (). The data passed when triggering this event should be only of type > Player. > How can I do that? It sound like dependant typing... > > Haven't tried it, and I don't know if it actually does what you want in the big picture. But you can do "dynamic" dependent typing with dummy (free) type variables. *type Player = Int --dummy types for the example type Rule = Int data Event d = New deriving Eq -- not necessary for this example, but you might want to enumerate other events. * *class Handled data where -- Corresponds to your "Data" type * *data Handler d = H (d -> IO ())* * * *instance Handled Player* *instance Handled Rule* * * *addEvent :: (Handled d) => Event d -> Handler d -> [(Event d, Handler d)] -> [(Event d, Handler)]* *triggerEvent :: (Handled d) => Event d -> d -> [(Event d, Handler d)] -> IO ()* * * Basically, this means that Events are "keyed" into separate spaces by the Handled types. (New :: Event Player) has a different type as (New :: Event Rule). You might want to look into ScopedTypeVariables.
_______________________________________________ Haskell-Cafe mailing list [email protected] http://www.haskell.org/mailman/listinfo/haskell-cafe
