Hi David, that may be also a way to go. I've also looked into this way (view patterns), unfortunately it seems that I will be obliged to maintain 2 parallel structures: for each Event instance, I will have to add a ViewEvent element as well carrying the same information:
instance Event Time where eventType = TimeEvent data EventType e where PlayerEvent :: EventType Player MessageEvent :: EventType (Message m) TimeEvent :: EventType Time That's why I like the all-GADT solution... Corentin On Tue, Sep 11, 2012 at 6:46 PM, David Menendez <d...@zednenem.com> wrote: > I'm not sure I understand > > > On Tue, Sep 11, 2012 at 11:06 AM, Corentin Dupont > <corentin.dup...@gmail.com> wrote: > > Yes. > > That's fantastic! This GADT is the missing piece of my puzzle. I > transformed > > a bit your solution, polluting it with some classes instances and > fleshing > > the functions: > > > > data Player = Arrive | Leave deriving (Show, Typeable, Eq) > > data Message m = Message String deriving (Show, Typeable, Eq) > > > > > > data Data a where > > PlayerData :: Int -> Data Player > > MessageData :: m -> Data (Message m) > > > > data Handler where > > Handler :: (Typeable e) => e -> (Data e -> IO ()) -> Handler > > > > instance forall e. (Typeable e) => Typeable (Data e) where > > typeOf _ = mkTyConApp (mkTyCon( ("Expression.EventData (" ++ (show $ > > typeOf (undefined::e))) ++ ")" )) [] > > > > addEvent :: (Typeable e) => e -> (Data e -> IO ()) -> [Handler] -> > [Handler] > > addEvent e h hs = (Handler e h) : hs > > > > triggerEvent :: (Eq e, Typeable e) => e -> Data e -> [Handler] -> IO () > > triggerEvent e d hs = do > > let filtered = filter (\(Handler e1 _) -> e1 === e) hs > > mapM_ f filtered where > > f (Handler _ h) = case cast h of > > Just castedH -> do > > castedH d > > Nothing -> return () > > > > viewEvent :: (Typeable e) => e -> IO() > > > > viewEvent event = do > > case cast event of > > Just (a :: Player) -> putStrLn $ "Player" ++ show a > > > > Nothing -> return () > > case cast event of > > (Just (Message s)) -> putStrLn $ "Player" ++ s > > Nothing -> return () > > > > > > Unfortunately, I still cannot pattern match on the events to view them > > (viewEvent won't compile)... > > Mixing GADTs and Typeable seems like a bad idea. If you really don't > want to put viewEvent in the Event typeclass, but the class of events > is closed, you could use a GADT to witness the event type. > > class Event e where > eventType :: EventType e > ... > > data EventType e where > PlayerEvent :: EventType Player > MessageEvent :: EventType (Message m) > > viewEvent :: Event e => e -> IO () > viewEvent = viewEvent' eventType > > viewEvent' :: EventType e -> e -> IO () > viewEvent' PlayerEvent e = ... > viewEvent' MessageEvent (Message s) = ... > > -- > Dave Menendez <d...@zednenem.com> > <http://www.eyrie.org/~zednenem/> >
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe