如何在Javascript中实现Haskell的FRP行为类型?

19 javascript haskell functional-programming frp reactive-programming

我想了解Haskell中功能反应式编程的原始含义,以及它与Javascript中FRP的实际应用有何不同.不幸的是,我对Haskell只有肤浅的理解,必须坚持使用Javascript.

这是我尝试Behavior用无类型语言实现Haskell的数据类型:

// 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);
};
Run Code Online (Sandbox Code Playgroud)

A是必要的,因为我必须改变x由调用堆栈保存的初始值.函数体从左到右进行求值,并返回逗号运算符的最后一个操作数的值,,即破坏性更新的版本x.

target.addEventListener 只是将给定的处理程序订阅给给定的DOM HTML元素.

behavior返回一个启用只读访问权限的函数x.

此实现在Javascript中引入了只读抽象数据类型,其值仅存在于高阶函数的调用堆栈中.如果DOM事件仅由GUI用户触发,则程序无法改变类型的值behavior.它只能轮询它们以观察时变效应.

这种方法与Haskell的远程可比Behavior吗?

这是一个小例子 - 鼠标点击计数器(计数4秒):

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:"));
Run Code Online (Sandbox Code Playgroud)

Reg*_*rtz 1

behavior尽管 FRP 事件和 DOM 事件没有任何共同点,但您的实现更接近 FRP 术语中的事件。FRP 的核心是抽象了连续(而不是离散)时间的概念。Behavior a表示类型值的连续流a;因此,它的含义是时间到价值的函数。

\n\n

康纳尔·艾略特(Conal Eliott)就是这样定义它的:

\n\n
\xce\xbc :: Behaviour a -> (Time -> a)\n
Run Code Online (Sandbox Code Playgroud)\n\n

他用这种符号来描述某物的含义,将其描述为从某物到具体计算值的函数。

\n\n

事件是“时间冻结的行为”,即它们代表特定时刻发生的值:

\n\n
\xce\xbc :: Event a -> [(Time, a)]\n
Run Code Online (Sandbox Code Playgroud)\n\n

因为 Haskell 是一种惰性语言,所以值流可以表示为列表,这就是上面所说的。

\n\n

奇怪的是,没有多少 FRP 实现能够忠实于最初的想法,因为(我认为)很难想出连续时间\xe2\x80\x94 的高性能实现,这个 C++ 似乎很接近

\n\n

我鼓励您在线观看 Conal Eliott 的演讲,他是我见过的一些最优雅的 API 设计,他的解释非常清晰。

\n