怎么运行的
Yes, foldp
保留一些内部状态。保存整个历史记录将是一种浪费,而且还没有完成。
如果你使用foldp
在代码中多次执行不同的操作或具有不同的输入信号,那么每个实例将保持其自己的本地状态。例子:
import Keyboard
plus = (foldp (\dir presses -> presses + dir.x) 0 Keyboard.arrows)
minus = (foldp (\dir presses -> presses - dir.x) 0 Keyboard.arrows)
showThem p m = flow down (map asText [p, m])
main = lift2 showThem plus minus
但是,如果您使用来自 Foldp 的结果信号两次,则编译后的程序中将只有一个 Foldp 实例,所产生的更改将仅在两个位置使用:
import Keyboard
plus = (foldp (\dir presses -> presses + dir.x) 0 Keyboard.arrows)
showThem p m = flow down (map asText [p, m])
main = lift2 showThem plus plus
主要问题
如果确实如此,那么这是否违反了函数式编程原则,因为 main 现在维护内部状态(或者至少foldp
does)?
函数式编程没有任何人人都使用的伟大规范定义。有许多允许使用可变状态的函数式编程语言的示例。其中一些编程语言向您表明值在类型系统中是可变的(您可以看到 Haskell 的State a
输入这样的内容,但这实际上取决于您的观点)。
但什么是可变状态呢?什么是可变值?它是程序内部的一个值,是可变的。也就是说,它可以改变。不同的时间可能有不同的事情。啊,但我们知道 Elm 如何称呼随时间变化的值!那是一个Signal
.
所以真的是一个Signal
在 Elm 中是一个可以随时间变化的值,因此可以被视为变量、可变值或可变状态。只是我们非常严格地管理这个值,只允许对Signal
s。这样一个Signal
可以基于其他Signal
s 在你的程序中,或者来自图书馆或者来自外部世界(想想像这样的输入Mouse.position
)。谁知道外界是如何得出这个信号的!所以允许你自己的Signal
s 基于过去的值Signal
s其实还可以。
结论/TL;DR
你可以看到Signal
作为可变状态的安全包装。我们假设来自外界的信号(作为程序的输入)是不可预测的,但因为我们有这个仅允许 lift/sample/filter/foldp 的安全包装器,所以您编写的程序是完全可预测的。副作用是被包含和管理的,因此我认为它仍然是“函数式编程”。