Я работаю над программой, использующей reactive-banana, и мне интересно, как структурируйте мои типы с помощью основных строительных блоков FRP.
Например, вот упрощенный пример из моей реальной программы: скажем, моя система состоит в основном из виджетов — в моей программе фрагментов текста, которые меняются со временем.
я мог бы иметь
newtype Widget = Widget { widgetText :: Behavior String }
но я мог бы также
newtype Widget = Widget { widgetText :: String }
и используйте Behavior Widget
, когда я хочу поговорить о поведении, изменяющемся во времени. Это, кажется, делает вещи «упрощенными» и означает, что я могу использовать Behavior
операции более напрямую, вместо того, чтобы распаковывать и перепаковывать виджеты для этого.
С другой стороны, первый, кажется, избегает дублирования в коде, который фактически определяет виджеты, поскольку почти все виджеты меняются со временем, и я определяю даже те немногие, которые не меняются с помощью Behavior
, поскольку это позволяет мне комбинировать их. с остальными более последовательно.
В качестве другого примера, с обоими представлениями имеет смысл иметь экземпляр Monoid
(и я хочу иметь его в своей программе), но реализация для последнего кажется более естественной (поскольку это просто тривиальное поднятие моноида списка до Новый тип).
(Моя реальная программа использует Discrete
, а не Behavior
, но я не думаю, что это важно.)
Аналогично, следует ли использовать Behavior (Coord,Coord)
или (Behavior Coord, Behavior Coord)
для представления 2D-точки? В этом случае первое кажется очевидным выбором; но когда это запись из пяти элементов, представляющая что-то вроде объекта в игре, выбор кажется менее очевидным.
По сути, все эти проблемы сводятся к:
При использовании FRP, на каком уровне следует применять тип Behavior
?
(Тот же вопрос относится и к Event
, хотя и в меньшей степени.)