У меня есть связанная проблема в одном из моих проектов, в котором используется нечто похожее на архитектуру 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 разработчика.Вы можете уменьшить сложность, сегментируя сети, что является хорошим решением.В своем проекте я представил много структуры сети, заставляя реагирующих участников соответствовать определенной модели контроллера и создавая четко определенные средства взаимодействия этих моделей.Так как мои контроллеры являются постоянными, все настроено статически, но это может быть сделано динамически, в этом случае, вероятно, у меня будет диспетчер контроллеров, запущенный в одном потоке, и действия, которые генерируют новые контроллеры (такие как открытие нового окна), отправятсообщение в ветку для создания нового контроллера.