В этом подходе Typeable не используется. Нужно завести класс Event, обработчик listen будет его методом (в данном случае единственным).
class Event a where
listen :: a -> IO ()
instance Event KeyboardEvent where ...
instance Event MouseEvent where ...
Теперь есть два пути. Первый — без построения объектов. Вместо того, чтобы класть в список события, положим туда события вместе с обработчиками:
[listen (Letter x), listen LeftBtn]
Ничего другого ведь мы с событиями делать не собираемся, правильно? Здесь нам помогает ленивость, а в энергичном языке мы бы положили отложенный вызов (\() -> listen (Letter x)).
Если у класса несколько методов, и мы хотим таскать туда-сюда списки объектов, не говоря заранее, какой метод мы собираемся применять, можно воспользоваться экзистенциальными типами. Но здесь я покажу опять на примере события, с единственным методом. Пусть опять определен класс Event и его инстансы. Теперь так:
{-# LANGUAGE ExistentialQuantification #-}
class Event a where
listen :: a -> IO ()
data EventObj = forall a . (Event a) => EventObj a
instance Event EventObj where
listen (EventObj a) = listen a
Теперь можно класть в список события
x = [EventObj LeftBtn, EventObj IdleEvent]
и вызывать для каждого из них listen.
Компилятор Хаскеля невидимо для программиста строит из EventObj натуральный объект, очень похожий на объект из Java или C++: данные (типа "некий a класса Event") плюс словарь методов (все методы класса Event для данного a) — то, что на ОО-жаргоне называется vtable.
no subject
Теперь есть два пути. Первый — без построения объектов. Вместо того, чтобы класть в список события, положим туда события вместе с обработчиками:
[listen (Letter x), listen LeftBtn]
Ничего другого ведь мы с событиями делать не собираемся, правильно? Здесь нам помогает ленивость, а в энергичном языке мы бы положили отложенный вызов (\() -> listen (Letter x)).
Если у класса несколько методов, и мы хотим таскать туда-сюда списки объектов, не говоря заранее, какой метод мы собираемся применять, можно воспользоваться экзистенциальными типами. Но здесь я покажу опять на примере события, с единственным методом. Пусть опять определен класс Event и его инстансы. Теперь так:
Теперь можно класть в список события
x = [EventObj LeftBtn, EventObj IdleEvent]
и вызывать для каждого из них listen.
Компилятор Хаскеля невидимо для программиста строит из EventObj натуральный объект, очень похожий на объект из Java или C++: данные (типа "некий a класса Event") плюс словарь методов (все методы класса Event для данного a) — то, что на ОО-жаргоне называется vtable.