http://anonymous8216.livejournal.com/ ([identity profile] anonymous8216.livejournal.com) wrote in [personal profile] lomeo 2009-02-05 03:12 pm (UTC)

В этом подходе 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.

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting