3

我对 Elm 比较陌生,并且被 Elm 处理 GUI 的方式深深吸引。但是经过深思熟虑后,我发现很难有效地仅更新列表或手指树中的一个元素(就像 Haskell 中的手指树,如果它已经存在于 Elm 的库中),它位于 Signal 下,并且它的大小也有所不同与时间抗衡。

具体来说,要表达一个动态的手指树,我们必须写

Signal [ {-手指树的元素类型-} ]

但是如果我们想有效地更新手指树的一个元素,我们必须写

Signal [ Signal {-核心数据类型-} ]

但是在 Elm 中 Signal 不是 Monad,那么如何将两层 Signals 扁平化为一层呢?

评论 1:我不详细了解 Elm 在这种情况下的行为。重新处理整个手指树只是我的猜测。

注释 2:例如,假设我们有一个信号值,标记为s,类型为Signal (fingerTree Int),以及以下函数,标记为f,其输入为s,例如,lift (fmap (+1))其类型为Signal (fingerTree Int) -> Signal (fingerTree Int)。如果s只有一个元素发生了变化,函数f必须对s. 显然,这是在浪费时间,我不确定 Elm 是否足够聪明,可以检测到不可变性。

4

1 回答 1

5

TL;DR:将您的逻辑/数据处理实现为纯函数,并将它们提升为转换信号。

诀窍是编写一个processList : [elementType] -> [elementType]提供您想要的逻辑的函数(检查第三个元素是否是摆动器并将其更改为摆动器或您想要做的任何事情),然后使用具有类型的提升功能

lift : (a -> b) -> Signal a -> Signal b

喜欢lift processList mySignalThatProducesLists编辑使用产生的mySignalThatProducesLists数据processList

这里的主要思想是将逻辑和数据处理编码为纯函数,然后使用lift. 就像每次更新源信号中的数据时,Elm 都会自动重新应用该函数。

如果您习惯于在 Haskell 中编程,您可以将其视为一些不透明 Time 类型的新类型Signal a包装器,并将. 你不需要有一个单子来编辑数据。Time -> aliftfmap

还有用于提升具有多个参数的函数的函数,因此再次使用 Haskell 类比,您基本上具有 Applicative 仿函数的功能lift2lift3

他们没有 Monad 的原因是它强加了降低效率的实现细节。可能那里有一些我没有发现的 ArrowApply 等价物(这会给你一个与 Monad 相当的可表达性),但我不确定是否存在。

于 2014-10-25T12:18:04.253 回答