OK, so here's my last attempt. What do you think?<br>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.<br>
<i><br>data NewPlayer = NewPlayer deriving (Typeable, Eq)<br>data NewRule = NewRule deriving (Typeable, Eq)<br><br>class (Eq e, Typeable e) => Event e<br>instance Event NewPlayer<br>instance Event NewRule<br><br>data family EventData e<br>
data instance EventData NewPlayer = P Int<br>data instance EventData NewRule = R Int<br>instance Typeable1 EventData where <br> typeOf1 _ = mkTyConApp (mkTyCon "EventData") []<br><br>data EventHandler = forall e . (Event e) => EH e (EventData e -> IO ())<br>
<br>addEvent :: (Event e) => e -> (EventData e -> IO ()) -> [EventHandler] -> [EventHandler] <br>addEvent e h ehs = (EH e h):ehs<br><br><br>triggerEvent :: (Event e) => e -> (EventData e) -> [EventHandler] -> IO ()<br>
triggerEvent e d ehs = do<br> let r = find (\(EH myEvent _) -> cast e == Just myEvent) ehs<br> case r of<br> Nothing -> return ()<br> Just (EH _ h) -> case cast h of<br> Just castedH -> castedH d<br>
Nothing -> return ()<br><br>-- TESTS<br>h1 :: EventData NewPlayer -> IO ()<br>h1 (P a) = putStrLn $ "Welcome Player " ++ (show a) ++ "!"<br>h2 :: EventData NewRule -> IO ()<br>h2 (R a) = putStrLn $ "New Rule " ++ (show a)<br>
eventList1 = addEvent NewPlayer h1 []<br>eventList2 = addEvent NewRule h2 eventList1<br><br>trigger1 = triggerEvent NewPlayer (P 1) eventList2 --Yelds "Welcome Player 1!" <br>trigger2 = triggerEvent NewRule (R 2) eventList2 --Yelds "New Rule 2" </i><br>
<br><br>Thanks again!!<br>Corentin<br><br><div class="gmail_quote">On Sun, Jun 17, 2012 at 12:46 AM, Alexander Solla <span dir="ltr"><<a href="mailto:alex.solla@gmail.com" target="_blank">alex.solla@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br><br><div class="gmail_quote"><div class="im">On Sat, Jun 16, 2012 at 3:31 PM, Corentin Dupont <span dir="ltr"><<a href="mailto:corentin.dupont@gmail.com" target="_blank">corentin.dupont@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Alexander,<br>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:<br>NewPlayer<br>NewRule<br>Message<br>
User<br><br>I want to associate the following data types with each, to pass to there respective handlers:<br>NewPlayer ---> Player<br>
NewRule ---> Rule<br>
Message ---> String<br>
User ---> String<br><br>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...<div><div><br></div></div></blockquote><div>
<br></div></div><div>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.</div>
</div>
</blockquote></div><br>