我想了解Haskell中函数式反应编程的最初含义,以及它与玻璃钢在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只是向给定的DOM元素订阅给定的处理程序。
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:"));
发布于 2018-03-17 22:33:01
在玻璃钢术语中,您的behavior实现更接近于事件,尽管玻璃钢事件和DOM事件没有任何共同之处。在其核心,玻璃钢抽象了连续(相对于离散)时间的概念。Behavior a表示a类型的值的连续流;因此,它的意义是作为一个函数从一个时候到另一个值。
Conal Eliott是这样定义它的:
μ :: Behaviour a -> (Time -> a)这个表示法是他用来描述某物的意义的,从那个东西到一个具体的计算值的函数。
事件是“冻结在时间中的行为”,即它们代表在特定时刻发生的价值:
μ :: Event a -> [(Time, a)]因为Haskell是一种懒惰的语言,所以值流可以表示为列表,这就是上面所说的。
奇怪的是,没有多少玻璃钢的实现保持了原来的想法,因为(我认为)很难想出一个连续的时间-这个C++似乎很接近的性能实现。
我鼓励大家在网上观看Conal Eliott的演讲,他的是我见过的一些最优雅的API设计,他用清晰的语言来解释它。
https://stackoverflow.com/questions/42373923
复制相似问题