Функциональное реактивное программирование - это подход, позволяющий четко определять побочные эффекты программ.
Недавно я использовал rxscala, который является портом портов Java/ Scala для ReactiveX. Он основан на понятии Observable
, который можно рассматривать как потоки значений определенного типа.
Для этого вопроса я хочу исключить подходы FRP, которые обрабатывают непрерывные изменения времени (сигналы).
Построение новых наблюдений из старых
Эти Observables могут быть объединены с использованием множества различных функций для создания новых наблюдаемых. Они похожи на функции, которые могут применяться к коллекциям. И это уже достаточно хорошо понято, как мы знаем Foldable
, Traversable
, Applicative
, Monads
и тому подобное.
Действительно, наблюдаемые являются складными, проходящими монадами, как обычные коллекции. Но эти черты могут быть реализованы несколькими способами для наблюдаемых, поскольку наблюдаемое содержит гораздо больше информации (информацию о времени для каждого элемента), чем обычная коллекция. И результат также должен быть снабжен информацией о времени.
Две реализации Monad
Например, монадический join
(flatMap
в Scala) может быть реализован, по крайней мере, двумя разными, правдоподобными способами:
-
Под
switch
между вложенными наблюдаемыми, что приводит к усечению текущего активного наблюдаемого, как только следующий начинает излучать, илиВизуализация переключателя RxJava http://reactivex.io/documentation/operators/images/switch.c.png
-
merge
вложенных наблюдаемых, не отбрасывая или не задерживая никаких событий.Визуализация слияния RxJava http://reactivex.io/documentation/operators/images/mergeDelayError.C.png
-
... и многое другое (см. комментарии)
Ограничения
Я очень доволен предоставленным репертуаром функций combinator, но я постоянно сталкиваюсь с ситуациями, когда я не могу добиться того, чего хочу, и я должен вернуться к некоторому параллельному программированию.
Отсутствующие комбинаторы или мозги?
Теперь мне интересно, я просто слишком глуп, чтобы построить желаемое поведение с использованием существующих комбинаторов. Или это так, что функции комбинатора, доступные в rxscala, недостаточны для создания любого мыслимого поведения?
Вопрос
Я прошу доказательства того, что некоторого базового набора комбинационных функций B
достаточно, чтобы создать "все мыслимые наблюдаемые" из некоторых входных наблюдаемых.
Возможно, самой сложной частью может быть определение "все мыслимые наблюдаемые". Может быть, сообщество Haskell произвело что-то вроде этого?