如何使用函数式编程“跟踪”用户活动?

问题描述:

TL;博士如何使用函数式编程“跟踪”用户活动?

在调用每一帧上的功能onEnterFrame一个程序,你如何存储和变异状态?例如,如果你正在制作一个关卡编辑器或一个绘画程序来跟踪状态,并且做出一些小的增量变化,那就是诱惑/诱惑/邀请。用最少的全局状态变化来处理这种事情的最好方法是什么?

长版:

在接受来自用户的输入,如鼠标点击和击键一个互动节目,我们可能需要保留的数据模型的状态的轨道。例如:

  • 是否选择了一些元素?
  • 鼠标光标悬停在某个元素上,哪一个?
  • 鼠标按钮持续多久?这是一个点击或拖动?

我们,有时需要进行小改动大模型:

  • 在一个关卡编辑器,我们可能需要一个墙添加到现有的大套预制件的。你不想重新创建集合,不是?

阅读弗里斯比教授的大部分,充分引导,到目前为止,有到与输入的一些源提取一块数据,对这些数据进行计算,并将结果传递给一些输出处理问题上有许多功能的解决方案。

有时,应用让用户交互并执行数据突变序列。例如,如果程序让用户在画布上绘制(如Paint),我们需要存储绘画的状态以及导致该状态的操作(用于撤消和记录/调试目的)?

什么state是可以接受的,我们应该绝对避免什么? 目前我的结论是,我们不应该只存储暂时需要的状态,我们应该将它直接传递给需要它的函数。

但是如果有几个函数需要特定的计算呢?就像我们检查鼠标光标是否悬停在特定区域的情况一样,为什么我们要重新计算?

有没有办法进一步减少全局状态的变化?

+0

我意识到,我的问题是这个问题的一个贫穷的重复: http://*.com/questions/1020653/how-can-you-do-anything-useful-without-mutable-state – zehelvion

+0

我建议阅读此: http://prog21.dadgum.com/23.html – zehelvion

存储状态不是问题。这是突变的全球状态,这是问题。有处理这个问题的解决方案。想到的是State Monad。但是,我不确定这是否适用于撤消操作。但它是一个开始的地方。

如果您只是想将问题看作初始状态和一组操作,那么您可以将操作看作可以遍历的List(头部为最新操作)。撤销一组操作可以通过遍历列表的第一个n元素和cons - 将这些操作的反向操作添加到列表中。

这样你根本不会修改全局状态。

+0

存储全局状态和突变全局状态之间的区别并不清楚,因为如果你正在存储状态,你可能正在更新它? 您是否建议如果某些模型对某些主流程很重要,我应该将其注入处理该流程的函数中? – zehelvion

+0

状态monad将状态传递给每个'转换'并返回一个新状态。那样没有全球状态发生变异。使用List是为了模拟一个事件存储,其中状态是通过(例如)从操作序列上的初始状态'折叠'到某个最终状态而得到的。同样,不需要改变全局状态。 – melston