Как обрабатывать несколько окон и единую структуру данных в реактивном банане - PullRequest
2 голосов
/ 28 октября 2011

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

Допустим, у меня есть центральная структура данных. Пользователь может свободно открывать и закрывать любое количество различных типов окон, которые отображают данные и позволяют пользователю изменять их.

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

В других ситуациях, подобных этой, я поместил структуру данных в один канал, на который все отправляли обновления. И тогда структура данных будет «публиковать» обновления (события запуска), которые все «слушали» в окнах.

Ответы [ 2 ]

3 голосов
/ 28 октября 2011

У меня есть связанная проблема в одном из моих проектов, в котором используется нечто похожее на архитектуру MVC.Центральная структура данных упоминается как

-- the data is a tree, and it's kept as a zipper to the current node
Discrete MyDataZip

Вот сокращенная версия объявления моего контроллера:

data Controller st = Controller {
  dState      :: Discrete st
 ,eUpdateZip  :: Event (MyDataZip -> MyDataZip)
 ,eResponse   :: Event (IO ())
 ,bDiagChange :: Behavior (Diagram Cairo R2 -> Diagram Cairo R2)
 }

При создании большинство контроллеров получают ссылку на dZip :: Discrete MyDataZip,но нет возможности изменить его напрямую.Единственный способ для контроллера указать обновление - это поток eUpdateZip в структуре данных Controller.

Несколько контроллеров собраны в граф, который представляет собой просто список контроллеров, помещенных в оболочку экзистенциального типа.data EControl = forall st. EControl (Controller st).Я просто mconcat все отдельные параметры eUpdateZip, чтобы получить один поток Event (MyDataZip -> MyDataZip), который используется для создания Discrete MyDataZip.Все это работает, потому что создание новых контроллеров является чистым, так что это может быть сделано в том же let-связывании, что позволяет рекурсивную ссылку.

Открытие новых окон и других задач ввода-вывода выполняется в потоке eResponse,который аналогично mconcat d и затем передается в reactimate.

. Вы можете изучить darcs repo для получения более подробной информации, посмотрите в "src / Jaek / UI / Controllers /" и"src / Jaek / UI / ControlGraph.hs".

РЕДАКТИРОВАТЬ: Центральная проблема заключается в том, что одна большая сеть довольно громоздкая от POV разработчика.Вы можете уменьшить сложность, сегментируя сети, что является хорошим решением.В своем проекте я представил много структуры сети, заставляя реагирующих участников соответствовать определенной модели контроллера и создавая четко определенные средства взаимодействия этих моделей.Так как мои контроллеры являются постоянными, все настроено статически, но это может быть сделано динамически, в этом случае, вероятно, у меня будет диспетчер контроллеров, запущенный в одном потоке, и действия, которые генерируют новые контроллеры (такие как открытие нового окна), отправятсообщение в ветку для создания нового контроллера.

1 голос
/ 30 октября 2011

В настоящее время невозможно добавить или удалить внешние события в сети событий после ее компиляции (начиная с версии реактивного банана 0.4.3). Другими словами, невозможно описать вашу задачу в одной сети событий. Однако вы можете использовать внешние события или несколько сетей событий, что приводит к таким решениям, как:

  • Сопоставить динамический набор окон со статическим набором источников событий (он же AddHandler вещи).
  • Или используйте одну сеть событий на окно и заставьте их взаимодействовать через внешние источники событий.
  • Или перекомпилируйте одну сеть событий каждый раз, когда новое окно добавляется или удаляется. К сожалению, внутреннее состояние будет потеряно, поэтому вы должны сделать его явным и захватить его извне (например, в IORef). (Это, вероятно, наименее удовлетворительное решение.)
...