[Haskell-cafe] type variable in class instance
Corentin Dupont
corentin.dupont at gmail.com
Tue Sep 11 17:06:30 CEST 2012
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)*...
Best,
Corentin
On Tue, Sep 11, 2012 at 4:10 PM, Sean Leather <leather at cs.uu.nl> wrote:
> On Tue, Sep 11, 2012 at 3:39 PM, Corentin Dupontwrote:
>
> @Oleg: Yes the set of events is closed and I would be much happier with a
>> GADT! But no matter how hard I tried I couldn't manage.
>> Here is the full problem:
>>
>> *{-# LANGUAGE ExistentialQuantification, TypeFamilies,
>> DeriveDataTypeable #-}
>>
>> import Data.Typeable
>>
>> -- | Define the events and their related data
>> class (Eq e, Typeable e, Show e) => Event e where
>> data EventData e
>>
>> -- | Groups of events
>> data PlayerEvent = Arrive | Leave deriving (Typeable, Show, Eq)
>>
>> -- | events types
>> data Player = Player PlayerEvent deriving (Typeable, Show, Eq)
>> data Message m = Message String deriving (Typeable, Show, Eq)
>>
>> -- | event instances
>> instance Event Player where data
>> EventData Player = PlayerData {playerData :: Int}
>> instance (Typeable m) => Event (Message m) where data EventData
>> (Message m) = MessageData {messageData :: m}
>>
>> -- | structure to store an event
>> data EventHandler = forall e . (Event e) =>
>> EH {eventNumber :: Int,
>> event :: e,
>> handler :: (EventData e) -> IO ()} deriving Typeable
>>
>> -- store a new event with its handler in the list
>> addEvent :: (Event e) => e -> (EventData e -> IO ()) -> [EventHandler] ->
>> [EventHandler]
>> addEvent event handler ehs = undefined
>>
>> -- trigger all the corresponding events in the list, passing the **data
>> to the handlers
>> triggerEvent :: (Event e) => e -> (EventData e) -> [EventHandler] -> IO ()
>> triggerEvent event edata ehs = undefined
>>
>> --Examples:
>> msg :: Message Int
>> msg = Message "give me a number"
>> myList = addEvent msg (\(MessageData n) -> putStrLn $ "Your number is: "
>> ++ show n) []
>> trigger = triggerEvent msg (MessageData 1) **myList --Yelds "Your number
>> is: 1"*
>>
>> Has you can see this allows me to associate an arbitrary data type to
>> each event with the type family "EventData". Furthermore some events like
>> "Message" let the user choose the data type using the type parameter. This
>> way I have nice signatures for the functions "addEvent" and "triggerEvent".
>> The right types for the handlers and the data passed is enforced at
>> compilation time.
>> But I couldn't find any way to convert this into a GATD and get rid of
>> the "Event" class......
>>
>
> Would this work?
>
> data Player = Arrive | Leave
> data Message m = Message String
>
> data Data a where
> PlayerData :: Int -> Data Player
> MessageData :: m -> Data (Message m)
>
> data Handler where
> Handler :: Int -> e -> (Data e -> IO ()) -> Handler
>
> addEvent :: e -> (Data e -> IO ()) -> [Handler] -> [Handler]
> addEvent = undefined
>
> triggerEvent :: e -> Data e -> [Handler] -> IO ()
> triggerEvent = undefined
>
> Regards,
> Sean
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20120911/2323bcad/attachment.htm>
More information about the Haskell-Cafe
mailing list