[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