OK, so here's my last attempt. What do you think? The Event class is optional (it works without because of EventData is enforcing the use of the right types) however, I find it more clear because it clearly specifies which types are events. * data NewPlayer = NewPlayer deriving (Typeable, Eq) data NewRule = NewRule deriving (Typeable, Eq) class (Eq e, Typeable e) => Event e instance Event NewPlayer instance Event NewRule data family EventData e data instance EventData NewPlayer = P Int data instance EventData NewRule = R Int instance Typeable1 EventData where typeOf1 _ = mkTyConApp (mkTyCon "EventData") [] data EventHandler = forall e . (Event e) => EH e (EventData e -> IO ()) addEvent :: (Event e) => e -> (EventData e -> IO ()) -> [EventHandler] -> [EventHandler] addEvent e h ehs = (EH e h):ehs triggerEvent :: (Event e) => e -> (EventData e) -> [EventHandler] -> IO () triggerEvent e d ehs = do let r = find (\(EH myEvent _) -> cast e == Just myEvent) ehs case r of Nothing -> return () Just (EH _ h) -> case cast h of Just castedH -> castedH d Nothing -> return () -- TESTS h1 :: EventData NewPlayer -> IO () h1 (P a) = putStrLn $ "Welcome Player " ++ (show a) ++ "!" h2 :: EventData NewRule -> IO () h2 (R a) = putStrLn $ "New Rule " ++ (show a) eventList1 = addEvent NewPlayer h1 [] eventList2 = addEvent NewRule h2 eventList1 trigger1 = triggerEvent NewPlayer (P 1) eventList2 --Yelds "Welcome Player 1!" trigger2 = triggerEvent NewRule (R 2) eventList2 --Yelds "New Rule 2" * Thanks again!! Corentin On Sun, Jun 17, 2012 at 12:46 AM, Alexander Solla <alex.solla@gmail.com>wrote:
On Sat, Jun 16, 2012 at 3:31 PM, Corentin Dupont < corentin.dupont@gmail.com> wrote:
Hi Alexander, sorry my initial example was maybe misleading. What I really what to do is to associate each event with an arbitrary data type. For example, consider the following events: NewPlayer NewRule Message User
I want to associate the following data types with each, to pass to there respective handlers: NewPlayer ---> Player NewRule ---> Rule Message ---> String User ---> String
Message and User have the same data type associated, that's why we can't use this type as a key to index the event...
In that case, you definitely want FunctionalDependencies or TypeFamilies, and will probably want to drop the constraint (Handler e d) on Event e (if it doesn't work), and maybe enforce it with explicit exports.