Ищем `flatten :: Event [a] -> Event a` в Reactive Banana

Я ищу что-то вроде flatten :: Event [a] -> Event a (поменяйте местами [] на Foldable f => f, если хотите), которое будет генерировать отдельное событие для каждого a в списке Event, например split в старой версии sodium.

Я подозреваю, что это как-то возможно с switchE, но тогда мне понадобилась бы функция типа [a] -> Event a.

Я мог бы сделать это сам с помощью newEvent, но есть ли встроенная функция в reactive-banana?

Изменить:

На самом деле, я не уверен, что смогу реализовать это с помощью newEvent.

flatten :: Foldable f => f a -> Banana.MomentIO (Banana.Event a)
flatten xs = do
  (event, fire) <- Banana.newEvent
  liftIO $ forkIO $ mapM_ fire xs
  return event 

Будет ли fire блокироваться до тех пор, пока не появятся подписчики, или сразу вернется, если их нет?

Редактировать 2:

Глядя на реализации newAddHandler моя реализация выше не будет работать, потому что все события, возможно, запускаются до того, как какие-либо обработчики смогут зарегистрироваться.


person Sebastian Graf    schedule 29.04.2016    source источник


Ответы (1)


Это кажется невозможным. Согласно заметкам в блоге Генриха Апфельмуса, Event не t поддерживают одновременные события. Это относительно недавнее изменение; пост датирован августом прошлого года, а версия 1.0 была выпущена в октябре. Этого точно не было, когда я впервые изучил Reactive Banana несколько лет назад.

Но Event [a] кажется разумным способом представить набор случайных событий в первую очередь. Зачем нужно его выравнивать?

person Benjamin Hodgson♦    schedule 29.04.2016
comment
Я хочу выполнить действие IO для каждого из этих a (выборка/клонирование репозиториев git), а затем выполнить нижестоящий код после каждого из них (например, собрать и протестировать проект). Я бы предпочел делать это «сначала в глубину» (запуск соответствующей выборки и последовательной сборки), а не «сначала в ширину» (запуск всех выборок, затем запуск всех сборок). Существуют также другие источники событий, которые производят одиночные a, но я, конечно, мог бы обернуть их в одиночные списки. - person Sebastian Graf; 29.04.2016
comment
На самом деле, я думаю, что выполнение IO — это единственное, что имеет смысловое значение. - person Sebastian Graf; 29.04.2016
comment
Я думаю, что fmap (traverse (clone >=> build)) :: Event [Project] -> Event (IO ()) сделал бы это, нет? - person Benjamin Hodgson♦; 29.04.2016
comment
Да, но я бы предпочел разделить clone и build на свои собственные события/стрелки, потому что build также может запускаться другими событиями. Но спасибо за предложения, я пойду попробую что-нибудь. - person Sebastian Graf; 29.04.2016
comment
Просто сделайте clone и build отдельными функциями, как я предложил выше, и fmap (traverse build) над другими событиями, которые могут вызвать сборку. - person Benjamin Hodgson♦; 30.04.2016
comment
Я побегу с этим! Хотя это оставляет меня немного озадаченным. как я должен структурировать свое приложение. Первоначально я думал, что могу просто иметь много модулей, экспортирующих Event a -> MomentIO (Event b) стрелки, скрывающие ввод-вывод и состояние в корректной манере. Теперь я должен «нарушить» это правило с помощью build, хотя это кажется нормальным, потому что в любом случае это приемник в сети. - person Sebastian Graf; 30.04.2016
comment
Событие не поддерживает одновременные события. Кстати, это относится и к более поздним версиям натрия. - person Heinrich Apfelmus; 30.04.2016
comment
@Sebastian Себастьян Я бы так не структурировал код. Ограничьте использование модуля Reactive.Banana.Frameworks точкой входа вашего приложения, которая должна состоять только из вызовов fromAddHandler (для привязки входных данных) и reactimate (для привязки выходных данных). Отсутствие MomentIO в модулях вашей библиотеки способствует компонуемости. - person Benjamin Hodgson♦; 30.04.2016
comment
Спасибо за ваши предложения. Я получил сеть, чтобы делать то, что я хочу сейчас. - person Sebastian Graf; 01.05.2016