Реактивный банан: привязки

Я работаю над небольшим пользовательским интерфейсом на основе терминала и хочу использовать Reactive Banana для описания взаимодействий. Единственное внешнее событие, которое меня интересует, это то, нажал ли пользователь клавишу.

Из того, что я узнал из документации Frameworks, я могу либо использовать опрос, чтобы получить состояние входного буфера терминала, либо передать «обработчик событий» в Reactive Banana. Я бы предпочел последнее, но я нахожу раздел обработки событий запутанным. Как бы я описал версию getChar, управляемую событиями? В конце концов, я хотел бы работать с потоком «Ключ события».

Я просмотрел привязки SDL и wx, но я не нашел в них особой помощи, поскольку они изобилуют особенностями, связанными с библиотекой, и я был бы очень признателен за более краткое объяснение того, как обработчики событий, циклы событий и Reactive Banana смешиваются. вместе.


person ftl    schedule 19.06.2017    source источник
comment
В Интернете можно найти множество примеров/учебников. Что вы пробовали и как это не сработало? (Функция, которая вам нужна для обработки событий пользовательского ввода, таких как нажатия клавиш, — это fromAddHandler)   -  person user2407038    schedule 20.06.2017
comment
Да, я думаю, что понял это, только после публикации. Кажется, мне просто нужно было немного отдохнуть. Я опубликую свой ответ, если есть интерес, в противном случае вопрос можно закрыть. Спасибо.   -  person ftl    schedule 20.06.2017
comment
Нет необходимости закрывать его - отредактируйте вопрос, включив в него код, показывающий, где вы изначально застряли, а затем опубликуйте ответ, содержащий найденное решение. Вопросы с самостоятельными ответами — вполне допустимый формат для SO! Вы не делаете этого для какого-то конкретного человека, у которого есть интерес; это для потомков всех будущих читателей.   -  person user2407038    schedule 20.06.2017


Ответы (1)


Как оказалось, работа с внешними событиями с помощью Reactive Banana невероятно гибкая и простая. Все, что нужно, это создать обработчик событий с «newAddHandler», который состоит из двух частей: «AddHandler», из которого события могут быть созданы с помощью функции reanimate, и обработчик, который должен вызываться связующим кодом (привязка) который связывает Reactive Banana с фреймворком (в моем случае я просто передаю результат getChar обработчику).

Вот пример кода, который повторяет нажатия клавиш:

echo = do
  (keyEventHandler, fire) <- newAddHandler

  -- Network Specification (echo keyboard input)
  let networkDescription =
      fromAddHandler keyEventHandler >>= -- Create event stream from handler
      reactimate . fmap print -- Map print over event stream

  compile networkDescription >>= actuate 

  -- Event Loop
  hSetBuffering stdin NoBuffering   
  forever $ do
      ready <- hReady stdin
      if ready
          then getChar >>= fire -- Create keyboad event
          else return ()

Преимущество реактивного банана в том, что функция обратного вызова «огонь» может быть вызвана из любого контекста. Таким образом, цикл событий может также выполняться в потоке или вызываться из библиотеки C. Подробнее об этом можно узнать в ответе Генриха на Как реализовать игровой цикл в реактивном банане?.

Однако ловить произвольные события ввода с клавиатуры без опроса не так просто, как я думал, POSIX этого не позволит (если не ошибаюсь), а даже если бы и разрешил, код не был бы переносимым. Также обратите внимание, что на компьютерах с Windows вам нужно нажать Enter, мне все еще нужно найти способ обойти эту проблему. Дополнительную информацию по этой проблеме можно найти в системе отслеживания ошибок Haskell.

person ftl    schedule 20.06.2017