[Haskell-cafe] type variable in class instance

David Menendez dave at zednenem.com
Tue Sep 11 18:46:57 CEST 2012


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/>



More information about the Haskell-Cafe mailing list