🔥

Тред (@thought_sync)


Это конечно, странный формат для твиттера. Но попробую.

Жил был дядька, звали его Conal Elliot и выпустил он в 1997 году статью, она называлась Functional Reactive Animation вместе с Paul Hudak.

Никто ее особо тогда не заметил, но почему-то спустя лет так 15 оказалось, что вся эта фигня подходит не только для анимаций, но и для UI.

После выхода статьи появилось много всяких ответвлений вроде: real-time frp, arrowized frp и так далее.

Но как только термин попал в наш фронтенд все, как обычно, начали называть этим термином все подряд. Хотите подробности, ссылка чуть ниже.

И на самом деле, оригинальная формулировка имеет ряд фундаментальных проблем.

Достаточно подробно фундаментальные проблемы FRP описаны в дипломной работе автора Elm. seas.harvard.edu/sites/default/…

Но зачем тогда я про это рассказываю? Там есть ряд интересных идей, которые потерялись в Elm (например) по разным причинам.

Ядро всей идеи, это некий тип Behaviour a, где a — это любой тип.

Behaviour a = T => a. То есть это функция от времени, которая возвращает значение типа «а».

Behaviour — это что-то вроде Observable, но только без отмены подписки и бесконечный в обе стороны. reactivex.io/documentation/…

Более того, и это важно, время в Behaviour непрерывно, то есть может быть дробью.

То есть, в DCTP ваша программа рисующая интерфейс это «Behaviour UI».

Функция, которая получает на вход время, а возвращает интерфейс. В абсолютно любой момент времени.

Насчет идеи программы, как функции есть хороший доклад @andrestaltz youtube.com/watch?v=1zj7M1…

Но в отличие от DCTP в Elm, к примеру. Есть (был) аналог behaviour = signal. Но он дискретный.

Почему это важно? Любые дискретные данные — это потеря информации. Они не «идеальны».

К примеру, есть растровая графика и векторная. Векторная графика — это полная информация, растровая — это потеря исходной информации.

Гораздо удобнее работать именно с векторной графикой, потому что не нужно делать предположений о характеристиках монитора заранее.

Решение о дискретизации принимается в самый последний момент, когда есть абсолютно вся информация о системе.

Чуть больше можно почитать в классической статье Why Functional Programming Matters. cs.kent.ac.uk/people/staff/d…

Непрерывное время, как явный аргумент вашей программы кажется довольно элегантной идеей.

Таким образом вы декларативно можете описывать процессы, которые зависят от времени. Увеличивая их инкапсуляцию.

Это легко себе представить на примере анимации. Обычно синхронизировать две анимации сложно, здесь это явное следствие архитектуры.

Как только время становится просто аргументом, вы можете работать с ним как с обычным значением. Растягивать, сжимать, поворачивать вспять.

Когда я думаю про это, всегда вспоминаю замечательную игры Braid. en.wikipedia.org/wiki/Braid_(vi…

Определить трансформацию над временем легко. «timeTrans :: Behavior UI -> Behavior T -> Behavior UI».

Это функция, которая принимает Behavior UI и T, а возвращает новый Behavior, в котором время себя ведет согласно второму аргументу.