如何解决我可以以纯函数方式改变变量吗?
我知道我可以将状态传递和状态 monad 用于纯粹的功能突变,但是 afaik 这不是就地的,我想要就地执行它的性能优势。
一个例子会很棒,例如给一个数加 1,最好在 Idris 中,但 Scala 也不错
附言有突变的标签吗?看不见
解决方法
不,这在 Scala 中是不可能的。
然而,在纯函数式语言中实现就地变异的性能优势是可能的。例如,让我们采用一个以纯函数方式更新数组的函数:
def update(arr: Array[Int],idx: Int,value: Int): Array[Int] =
arr.take(idx) ++ Array(value) ++ arr.drop(idx + 1)
我们需要在这里复制数组以保持纯度。原因是如果我们在原地改变它,我们就可以在调用函数后观察到:
def update(arr: Array[Int],value: Int): Array[Int] = {
arr(idx) = value
arr
}
以下代码在第一个实现中可以正常工作,但在第二个实现中会中断:
val arr = Array(1,2,3)
assert(arr(1) == 2)
val arr2 = update(arr,1,42)
assert(arr2(1) == 42) // so far,so good…
assert(arr(1) == 2) // oh noes!
纯函数式语言的解决方案是简单地禁止最后一个断言。如果您无法观察到原始数组发生变异的事实,那么就地更新数组没有任何问题!实现这一点的方法称为线性类型。线性值是您可以只使用一次的值。将线性值传递给函数后,编译器将不允许您再次使用它,从而解决了问题。
我知道有两种语言具有此功能:ATS 和 Haskell。如果你想了解更多细节,我推荐 Simon Peyton-Jones 的这个演讲,他解释了 Haskell 的实现:
对线性类型的支持已合并到 GHC:https://www.tweag.io/blog/2020-06-19-linear-types-merged/
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。