Реактивный банан: Как создать AddHandler?

В настоящее время я пытаюсь узнать FRP через Heinrich Apfelmus reactive-banana, который, кажется, является довольно хорошо документированной и простой библиотекой по сравнению с другие, на которые я смотрел.

Однако я не могу обернуть голову вокруг типа AddHandler. Скажем, я хочу использовать GLFW, чтобы нажимать кнопки мыши, чтобы у меня было что-то вроде eMouseButton :: Event (). Если посмотреть на примеры, мне кажется, что мне как-то придется использовать fromAddHandler, но я не знаю, как собрать этот аргумент AddHandler. Я думаю, что мне придется как-то использовать newAddHandler, но как?

Я думаю, что пример подключения reactive-banana к чему-то другому, кроме wx, очень помог.

Ответы

Ответ 1

newAddHandler используется следующим образом:

do (addHandler, fire) <- newAddHandler
   ...

addHandler - это AddHandler для перехода к reactive-banana, а fire - это функция типа a -> IO () (где a - ваш тип события), который запускает событие.

Например, вы, скорее всего, установите fire в качестве обратного вызова события мыши мыши GLFW, например:

registerMouseButton :: IO (Event MouseButton)
registerMouseButton = do
  (addHandler, fire) <- newAddHandler
  setMouseButtonCallback $ \button _ -> fire button
  fromAddHandler addHandler

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

An addHandler - это просто функция, которая принимает обратный вызов - a -> IO () - и регистрирует его для рассматриваемого события; он возвращает (изнутри IO) действие IO (), используемое для отмены регистрации этого обработчика, сделав полное определение addHandler следующим образом:

type AddHandler a = (a -> IO ()) -> IO (IO ())

Итак, куда входит newAddHandler? Простой: newAddHandler поддерживает список обработчиков для события и активирует их, когда выполняется fire x.

Вам не нужно newAddHandler, если, например, GTK + и многие другие распространенные инструментальные средства, ваш инструментарий уже имеет возможности регистрировать и отменять регистрацию нескольких обработчиков событий; если это так, вы должны написать собственную реализацию addHandler. Но если все, что он поддерживает, это один обратный вызов, вы должны использовать newAddHandler.

Обратите внимание, что вам никогда не нужно выставлять addHandler самому FRP-коду; они всего лишь внутренний клей, используемый для создания Event с внешних входов.