Обработка событий в Haskell - PullRequest
       35

Обработка событий в Haskell

14 голосов
/ 08 января 2012

Я хотел бы реализовать следующий сценарий в Haskell.У меня есть перечисляемый набор «событий», определенных следующим образом:

data MyEvent = Event1
             | Event2
             | Event3

Я хочу определить обработчики для этих событий, которые будут использоваться следующим образом:

eventLoop :: Handler h => h -> IO ()
eventLoop currentHandler = do
    event <- getNextEvent
    nextHandler <- currentHandler event
    eventLoop nextHandler

По сути, я хочуобработчики, чтобы иметь возможность возвращать себя или другого обработчика для обработки будущих событий.Это тип обработчиков, в которых я не уверен.

Моя первая идея состояла в том, чтобы определить обработчики как простые функции, но их тип получал бы бесконечно длинный:

myHandler :: Event -> IO (Event -> IO (Event -> ... ))

Я подозреваю, что это можетбыть решена с помощью класса типов, где каждый обработчик должен будет реализовать функцию для обработки событий (которая, в свою очередь, возвращает другой тип того же класса), но рекурсивное определение все равно будет применяться.Может ли кто-то более хорошо разбирающийся в системе типов указать мне правильное направление?Я также приветствую любые другие варианты этого.

Спасибо!

1 Ответ

17 голосов
/ 08 января 2012

Ну, «бесконечные» типы обычно составляют развернутые рекурсивные типы.Итак, вы могли бы сделать явную рекурсию, используя newtype:

newtype Handler = Handler { runHandler :: Event -> IO Handler }

Это также, вероятно, самое простое решение, поскольку оно устраняет необходимость в манипулировании классами типов и различными экземплярами, чтобы получитьразличное поведение - каждый обработчик может выбрать то, что он возвращает, поскольку он имеет единый интерфейс.

Обратите внимание, что во многих случаях определение класса типа для решения такого рода проблем совершенно излишне.Если вы имеете дело с полиморфным типом Handler h => h, все, что вы можете сделать с этим типом, это использовать функции класса этого типа.Если функции, определенные в этом классе типов, просты, вы можете избавить себя от многих хлопот, концептуально «предварительно применив» их.

...