Hi David,<br>that may be also a way to go. I&#39;ve also looked into this way (view patterns), unfortunately it seems that I will be obliged to maintain 2 parallel structures:<br>for each Event instance, I will have to add a ViewEvent element as well carrying the same information:<br>

<br>instance Event Time where <br>    eventType = TimeEvent<br><br>
data EventType e where<br>
    PlayerEvent :: EventType Player<br>
    MessageEvent :: EventType (Message m)<br>    TimeEvent :: EventType Time<br><br>That&#39;s why I like the all-GADT solution...<br>Corentin<br><br><div class="gmail_quote">On Tue, Sep 11, 2012 at 6:46 PM, David Menendez <span dir="ltr">&lt;<a href="mailto:dave@zednenem.com" target="_blank">dave@zednenem.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I&#39;m not sure I understand<br>
<div><div class="h5"><br>
<br>
On Tue, Sep 11, 2012 at 11:06 AM, Corentin Dupont<br>
&lt;<a href="mailto:corentin.dupont@gmail.com">corentin.dupont@gmail.com</a>&gt; wrote:<br>
&gt; Yes.<br>
&gt; That&#39;s fantastic! This GADT is the missing piece of my puzzle. I transformed<br>
&gt; a bit your solution, polluting it with some classes instances and fleshing<br>
&gt; the functions:<br>
&gt;<br>
&gt; data Player = Arrive | Leave deriving (Show, Typeable, Eq)<br>
&gt; data Message m = Message String deriving (Show, Typeable, Eq)<br>
&gt;<br>
&gt;<br>
&gt; data Data a where<br>
&gt;   PlayerData  :: Int -&gt; Data Player<br>
&gt;   MessageData :: m -&gt; Data (Message m)<br>
&gt;<br>
&gt; data Handler where<br>
&gt;   Handler :: (Typeable e) =&gt; e -&gt; (Data e -&gt; IO ()) -&gt; Handler<br>
&gt;<br>
&gt; instance forall e. (Typeable e) =&gt; Typeable (Data e) where<br>
&gt;     typeOf _  = mkTyConApp (mkTyCon( (&quot;Expression.EventData (&quot; ++ (show $<br>
&gt; typeOf (undefined::e))) ++ &quot;)&quot; )) []<br>
&gt;<br>
&gt; addEvent :: (Typeable e) =&gt; e -&gt; (Data e -&gt; IO ()) -&gt; [Handler] -&gt; [Handler]<br>
&gt; addEvent e h hs = (Handler e h) : hs<br>
&gt;<br>
&gt; triggerEvent :: (Eq e, Typeable e) =&gt; e -&gt; Data e -&gt; [Handler] -&gt; IO ()<br>
&gt; triggerEvent e d hs = do<br>
&gt;     let filtered = filter (\(Handler e1 _) -&gt; e1 === e) hs<br>
&gt;     mapM_ f filtered where<br>
&gt;         f (Handler _ h) = case cast h of<br>
&gt;             Just castedH -&gt; do<br>
&gt;                 castedH d<br>
&gt;             Nothing -&gt; return ()<br>
&gt;<br>
&gt; viewEvent :: (Typeable e) =&gt; e -&gt; IO()<br>
&gt;<br>
&gt; viewEvent event = do<br>
&gt;     case cast event of<br>
&gt;         Just (a :: Player) -&gt; putStrLn $ &quot;Player&quot; ++ show a<br>
&gt;<br>
&gt;         Nothing -&gt; return ()<br>
&gt;     case cast event of<br>
&gt;         (Just (Message s)) -&gt; putStrLn $ &quot;Player&quot; ++ s<br>
&gt;         Nothing -&gt; return ()<br>
&gt;<br>
&gt;<br>
&gt; Unfortunately, I still cannot pattern match on the events to view them<br>
&gt; (viewEvent won&#39;t compile)...<br>
<br>
</div></div>Mixing GADTs and Typeable seems like a bad idea. If you really don&#39;t<br>
want to put viewEvent in the Event typeclass, but the class of events<br>
is closed, you could use a GADT to witness the event type.<br>
<br>
class Event e where<br>
    eventType :: EventType e<br>
    ...<br>
<br>
data EventType e where<br>
    PlayerEvent :: EventType Player<br>
    MessageEvent :: EventType (Message m)<br>
<br>
viewEvent :: Event e =&gt; e -&gt; IO ()<br>
viewEvent = viewEvent&#39; eventType<br>
<br>
viewEvent&#39; :: EventType e -&gt; e -&gt; IO ()<br>
viewEvent&#39; PlayerEvent e = ...<br>
viewEvent&#39; MessageEvent (Message s) = ...<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Dave Menendez &lt;<a href="mailto:dave@zednenem.com">dave@zednenem.com</a>&gt;<br>
&lt;<a href="http://www.eyrie.org/~zednenem/" target="_blank">http://www.eyrie.org/~zednenem/</a>&gt;<br>
</font></span></blockquote></div><br>