Corentin Dupon wrote about essentially the read-show problem: > class (Typeable e) => Event e > > data Player = Player Int deriving (Typeable) > data Message m = Message String deriving (Typeable) > > instance Event Player > > instance (Typeable m) => Event (Message m) > > viewEvent :: (Event e) => e -> IO () > viewEvent event = do > case cast event of > Just (Player a) -> putStrLn $ show a > Nothing -> return () > case cast event of > Just (Message s) -> putStrLn $ show s > Nothing -> return ()
Indeed the overloaded function cast needs to know the target type -- the type to cast to. In case of Player, the pattern (Player a) uniquely determines the type of the desired value: Player. This is not so for Message: the pattern (Message s) may correspond to the type Message (), Message Int, etc. To avoid the problem, just specify the desired type explicitly > case cast event of > Just (Message s::Message ()) -> putStrLn $ show s > Nothing -> return () (ScopedTypeVariables extension is needed). The exact type of the message doesn't matter, so I chose Message (). BTW, if the set of events is closed, GADTs seem a better fit > data Player > data Message s > > data Event e where > Player :: Int -> Event Player > Message :: String -> Event (Message s) > > viewEvent :: Event e -> IO () > viewEvent (Player a) = putStrLn $ show a > viewEvent (Message s) = putStrLn $ show s _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe