Functional programming 纯函数式语言真的能保证不变性吗?

Functional programming 纯函数式语言真的能保证不变性吗?,functional-programming,immutability,purely-functional,Functional Programming,Immutability,Purely Functional,在纯函数式语言中,难道不能定义一个“赋值”操作符吗,比如说,“纯函数式语言,如Haskell,有建模命令式语言的方法,他们也不羞于承认它。” 具体见第7.5节: 因此,哈斯克尔最终只是 重新发明了命令轮 从某种意义上说,是的,I/O单子 这是一个小小的命令 Haskell内部的子语言,因此 程序的I/O组件可能会 与普通祈使句相似 代码。但有一个重要的问题 区别:没有什么特别的 用户需要处理的语义 特别是等式的 哈斯凯尔的推理并非如此 妥协的,妥协的,妥协的,妥协的 程序中的一元代码不会 从功能

在纯函数式语言中,难道不能定义一个“赋值”操作符吗,比如说,“纯函数式语言,如Haskell,有建模命令式语言的方法,他们也不羞于承认它。”

具体见第7.5节:

因此,哈斯克尔最终只是 重新发明了命令轮

从某种意义上说,是的,I/O单子 这是一个小小的命令 Haskell内部的子语言,因此 程序的I/O组件可能会 与普通祈使句相似 代码。但有一个重要的问题 区别:没有什么特别的 用户需要处理的语义 特别是等式的 哈斯凯尔的推理并非如此 妥协的,妥协的,妥协的,妥协的 程序中的一元代码不会 从功能方面减损 哈斯凯尔,一位经验丰富的功能工程师 程序员应该能够最小化 命令的命令部分 程序,仅对 最少量的顶级 测序。单子干净 将函数和 命令式程序组件 对比之下,命令式语言与 功能子集通常不存在 之间有明确的障碍吗 纯粹的功能性和命令性 世界

因此,函数式语言的价值不在于它们使状态变异变得不可能,而在于它们提供了一种方法,使程序的纯功能部分与状态变异部分分开

当然,您可以忽略这一点,以命令式风格编写整个程序,但这样您就不会利用该语言的功能,那么为什么要使用它呢

更新

你的想法并不像你想象的那样有缺陷。首先,如果一个只熟悉命令式语言的人想要循环一系列整数,他们可能会想,如果没有增加计数器的方法,这是如何实现的

当然,你只需要编写一个函数作为循环的主体,然后让它自己调用,每次调用函数都对应一个“迭代步骤”。并且在每次调用的范围内,参数具有不同的值,其作用类似于递增变量。最后,运行时可以注意到递归调用出现在调用结束时,因此它可以重用函数调用堆栈的顶部,而不是增加它()。即使是这个简单的模式也几乎具有您想法的全部特色——包括编译器/运行时悄悄介入并实际发生变异(覆盖堆栈顶部)。它不仅在逻辑上等同于一个带有变异计数器的循环,而且实际上它使CPU和内存在物理上做相同的事情


您提到了一个
GetStack
,它将以数据结构的形式返回当前堆栈。这确实违反了函数的纯度,因为每次调用它时,它必然返回不同的东西(没有参数)。但是一个函数
CallWithStack
,您将自己的函数传递给它,它将回调您的函数并将当前堆栈作为参数传递给它,怎么样?那太好了。工作原理有点像这样。

Haskell不会轻易地为您提供内省或“执行”调用堆栈的方法,因此我不会太担心这个特殊的奇怪方案。但是,一般来说,确实可以使用不安全的“函数”来破坏类型系统,例如
unsafePerformIO::IO a->a
。这样做的目的是使违反纯度变得困难,而不是不可能

事实上,在许多情况下,例如为C库进行Haskell绑定时,这些机制是非常必要的。。。通过使用它们,您将从编译器中卸下证明纯度的负担,并将其承担在自己身上


有一项建议是,通过将此类颠覆类型系统的行为定为非法,从而切实保障安全;我对它不太熟悉,但您可以阅读它。

不变性是语言的属性,而不是实现的属性


一个操作
a嗯,实际上我刚刚意识到Haskell不仅没有给你一种执行调用堆栈的方法,而且我认为任何纯语言都不能——调用堆栈是不断变化的,所以如果有一个函数GetCallStack,那么这将取决于状态,我认为这违反了纯度。我的小变通方法隐式调用了这个GetCallStack,所以看起来我的参数不正确。当然,除非有一个状态单子来跟踪每个函数调用的调用堆栈,但在这种情况下,我基本上只是在编写一个解释器。@Dax:没错,对于一个假设的
getCallStack::stack
来说,它是有用的,它必须根据您在程序中的位置产生不同的
堆栈
,这显然违反了引用透明性。是的,但我认为我的方案甚至可以在IO monad之外工作,因为它确实没有任何副作用。然而,我注意到我的论点中有一个缺陷,我在对pelotom的评论中强调了这一点。@Update虽然我没有看到任何绝对的证据,但在搜索“callcc纯度”报告时,我发现有几篇文章说callcc否定了所有的功能纯度。虽然我自己没有足够的智慧来证明这一点,但我必须说这是有道理的,因为CC虽然只是一个函数指针,但仍然是传递给函数的一个变异隐式上下文变量。正如我在另一篇评论中所说,如果你有一个特殊的延续状态monad,它会起作用,但是,除非我弄错了,否则这或多或少会减少到编写你自己的解释器。@Dax:对我来说这似乎是正确的,但如果你看看Haskell的类型,它是
monadcent m=>((a->mb)->ma)->ma
。continuation monad捕获continuation的语义,因此允许