[Haskell-cafe] type variable in class instance
Corentin Dupont
corentin.dupont at gmail.com
Tue Sep 11 19:03:46 CEST 2012
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 <dave at zednenem.com> wrote:
> I'm not sure I understand
>
>
> On Tue, Sep 11, 2012 at 11:06 AM, Corentin Dupont
> <corentin.dupont at 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 <dave at zednenem.com>
> <http://www.eyrie.org/~zednenem/>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120911/ac5eaaef/attachment.htm>
More information about the Haskell-Cafe
mailing list