Возьми на вооружение следующую интуицию: FRP это как Excel.
У тебя в Эксельке ячейки зависят друг от друга, иногда даже образуют циклы (Мелкософтовский Эксель это не позволяет, но в принципе почему бы и не разрешить).
Когда ты меняешь значение в одной из ячеек, все остальные зависимые пересчитываются, только в общем случае во время пересчёта функция может пойти в сеть или в файл, обрушиться с ошибкой, ошибки придётся комбинировать, и обновлять ещё может понадобиться не ячейки, а какие-нибудь элементы управления или состояние в базе данных.
Есть 2 главных стратегии при изменении одной из ячеек;
1. Пересчитывать весь граф зависимых ячеек транзитивно. Можно соптимизировать, когда мы точно знаем, что значение ячейки не изменится, и тем самым сэкономить на дальнейших обновлениях. (это push модель)
2. Просто класть замыкания в зависимые ячейки. Тогда если снаружи придёт запрос "дай мне значение ячейки X421", шестерёнки начинают крутиться и весь граф всех данных, которые влияют на данное значение начинает вычисляться. Это очень близко к ленивым вычислениям в Хаскеле. (это pull модель)
Ну и в принципе вот и всё FRP, остальные сложности в деталях обработки реактивных потоков значений.
Так при 2 подходе мы тоже можем не пересчитывать, если не надо. Дедупы же, дедупы повсюду)