Подтвердить что ты не робот

Как реализовать тип поведения Haskell FRP в Javascript?

Я хотел бы понять исходное значение функционального реактивного программирования в Haskell и то, как он отличается от фактического применения FRP в Javascript. К сожалению, у меня есть только поверхностное понимание Haskell и нужно придерживаться Javascript.

Вот моя попытка реализовать тип данных Haskell Behavior в нетипизированном языке:

// behavior :: String -> DOMHTMLElement -> a -> (a -> Event -> a) -> (a -> b)

const behavior = type => target => x => f => {
  const destructiveSet = y => (x = f(x) (y), x), // A
   handler = event => destructiveSet(event);

  target.addEventListener(type, handler, true);
  return g => g(x);
};

Строка A необходима, потому что мне нужно изменить начальное значение x, которое удерживается стеком вызовов. Тело функции оценивается слева направо и возвращает значение последнего операнда оператора запятой ,, то есть деструктивно обновляемую версию x.

target.addEventListener просто подписывает данный обработчик на данный HTML-элемент DOM.

Behavior возвращает функцию, которая позволяет доступ только для чтения к x.

В этой реализации вводится абстрактный тип данных для чтения в Javascript, значения которого существуют только в столах вызовов функций более высокого порядка. При условии, что события DOM запускаются только пользователями GUI, программа не имеет средств для изменения значений типа Behavior. Он может только опросить их, чтобы наблюдать изменяющийся во времени эффект.

Этот подход удаленно сопоставим с Haskell Behavior?

Вот небольшой пример - счетчик щелчков мыши (рассчитан на четыре секунды):

const behavior = type => target => x => f => {
  const destructiveSet = y => (x = f(x) (y), x),
   handler = event => destructiveSet(event);

  target.addEventListener(type, handler, true);
  return g => g(x);
};


const comp = f => g => x => f(g(x));

const K = x => y => x;

const I = x => x;

const get = I;

const defer = n => f => x => setTimeout(f, n, x);

const log = prefix => x => console.log(prefix, x);

const inc = x => x + 1;

const counter = behavior("click") (document) (0) (comp(K) (inc));


console.log("click on the section above");

counter(get); // 0

defer(4000) (counter) (log("counted clicks:"));
4b9b3361