非纯函数打破可组合性意味着什么?

use*_*545 13 haskell functional-programming

当有人说非纯函数打破了函数式语言的可组合性时,有人能给出一个解释实际意义的例子吗?

我想看一个可组合性的例子,然后看到相同的例子假设非纯函数以及未完成如何违反可组合性.

Dan*_*ner 11

一些可变状态过去困扰我的例子:

  • 我编写了一个函数来从一堆文本中删除一些信息.它使用一个简单的正则表达式来找到混乱中的正确位置并获取一些字节.它停止工作,因为我的程序的另一部分在正则表达式库中打开了区分大小写; 或者打开改变正则表达式解析方式的"魔法"模式; 或者当我写一个正则表达式匹配器的调用时,我忘记了其他任何一个旋钮.

    这在纯语言中不是问题,因为正则表达式选项显示为匹配函数的显式参数.

  • 我有两个线程想要在我的语法树上进行一些计算.我不顾一切地去做.由于两个计算都涉及重写树中的指针,因此当我按照之前很好的指针但由于其他线程所做的更改而过时时,我最终会发生segfaulting.

    这在纯语言中不是问题,其中树是不可变的; 两个线程返回生活在堆的不同部分的树,并且两者都可以看到原始原始而不受另一个的干扰.

  • 我本人并没有这方面的经验,但我听到其他程序员正在喋喋不休:基本上每个程序都使用OpenGL.管理OpenGL状态机是一场噩梦.如果你让州的任何一部分有点不对,那么每次通话都会犯一些愚蠢的错误.

    很难说在纯粹的环境中这会是什么样子,因为没有那么多广泛使用的纯图形库.对于3D方面,人们可以看一下fieldtrip,也许在第二方面,也许diagrams都来自Haskell-land.在每个场景中,场景描述都是组合的,人们可以轻松地将两个小场景组合成一个较大的场景,例如"将这个场景留在那个场景中","叠加这两个场景","在那个场景之后显示这个场景"等等,后端确保在渲染两个场景的调用之间挖掘底层图形库的状态.

上面描述的非纯场景中的共同线程是,人们无法查看一大块代码并弄清楚它在本地的作用.人们必须全面了解整个代码库,以确保他们理解代码块将会做什么.这是组合性的核心含义:可以组成一小块代码并理解它们的作用; 当他们被安排到一个更大的程序时,他们仍然会做同样的事情.


hug*_*omg 1

一方面,纯度可以实现惰性求值,而惰性求值可以实现某些在严格求值语言中无法实现的组合形式

例如,在 Haskell 中,您可以创建仅花费 O(1) 内存的mapfilter管道,并且您可以更自由地编写“控制流”函数,例如您自己的 ifThenElse 或 Control.Monad 上的内容。