“不组成”是什么意思?


35

我看到很多文本,特别是函数式编程文本,声称某些CS概念“不构成”。例如:锁不组成,单子不组成。

我一直很难找到这句话的确切含义。当我想到组合时,我想到的是函数组合或对象聚合(如“在继承中偏爱组合”),但这似乎并不是人们在这里使用它的意义。

有人可以解释在上述两个示例(即锁和单子)这样的表达式中使用该短语时的含义吗?


函数组合的含义比对象聚合的含义更接近。
Andres F.

粗略地和非正式地,如果您有两个使用锁的独立对象,则很难将它们粘在一起。(对于锁,很难不引入死锁;对于单子,类型可能会变得复杂)
user253751

Answers:


35

当人们说“ X不能组成”时,他们所谓的“组成”实际上只是意味着“放在一起”,而根据“ X”的确切含义,将它们组合在一起的方式和方式可能会非常不同。

另外,当他们说“不作文”时,它们的含义可能会略有不同:

  1. 句号,您根本不能将两个X放在一起。
  2. 可以将两个X放在一起,但结果可能不是X(IOW:X 在组合下关闭)。
  3. 您可以将两个X放在一起,但是生成的X可能无法按您期望的方式工作。

#1的示例是带有扫描器/词法分析器的解析器。您可能会听到“扫描仪/词法分析器不组成”的短语。这不是真的。它们的意思是“使用单独的词法分析阶段的解析器不组成”。

您为什么要组成解析器?好吧,假设您是一个JetBrains,Eclipse Foundation,Microsoft或Embarcadero之类的IDE供应商,并且您想为Web框架构建一个IDE。在典型的Web开发中,我们经常混合使用语言。您的HTML文件带有<script>包含ECMAScript和<style>包含CSS的元素。您有包含HTML,一些编程语言和一些模板语言metasyntax的模板文件。您不想为“ Python”,“嵌入在模板中的Python”,“ CSS”,“ HTML内的CSS”,“ ECMASCript”,“ HTML内的ECMAScript”,“ HTML”,“ HTML内”编写不同的语法突出显示模板”,依此类推。您要编写一个用于Python的语法突出显示器,一个用于HTML,一个编写用于模板语言的语法,然后将这三个组成模板文件的语法突出显示器。

但是,词法分析器将整个文件解析为令牌流,这仅对一种语言有意义。其他语言的解析器无法与词法分析器传递的标记一起使用。例如,Python解析器通常以这样的方式编写:词法分析器会跟踪缩进并将伪造的INDENTDEDENT令牌注入令牌流,因此即使Python的语法实际上并非如此,解析器也可以不受上下文限制。但是,HTML词法分析器将完全忽略空格,因为它在HTML中没有任何意义。

但是,无扫描器的解析器仅读取字符,可以将字符流传递给其他解析器,解析器随后可以将其递回,从而使它们的编写变得更加容易。

#2的示例是其中包含SQL查询的字符串。您可以有两个字符串,每个字符串中都有一个语法正确的SQL查询,但是如果将两个字符串连接在一起,则结果可能不是语法正确的SQL查询。这就是为什么我们有像查询代数ARel,它做的撰写。

锁是#3的示例。如果您有两个带锁的程序,并且将它们组合成一个程序,那么您仍然会有一个带锁的程序,但是即使两个原始程序是完全正确的,没有死锁和竞争,所得到的程序也不一定具有此功能。属性。正确使用锁是整个程序的全局属性,并且是编写程序时不会保留的属性。这与确实构成的交易不同。可以正确使用事务的程序可以与另一个这样的程序组成,并将产生一个可以正确使用事务的组合程序。


1
换句话说,“不组成”的意思是“不形成半群”(或者说,更强的单半体动物)。
乔恩·普迪

我不知道associtaivity的需要,所以更喜欢微捷码(这是我学到了字面上3秒前:-D)
约尔格W¯¯米塔格

但是,如果您问某人说“锁不构成”的含义,我很确定他们不会回答“我的意思是,带有锁的正确并发程序集和组合操作构成了Magma”。 。
约尔格W¯¯米塔格

嗯,当然不是。只是另一种措辞。我感觉到需要保持联系才能保持“平淡”的构图感觉,但没有强有力的论据来证明这一点。
乔恩·普迪

20

可组合性意味着您可以轻松可靠地将程序组件组合在一起,以产生更大的组件和更复杂的功能。

一些有助于使组件更易于组合的事情:

  1. 幂等。如果多次调用相同的参数值,幂函数将始终产生相同的输出或副作用。因为函数调用的结果是可预测的,所以这提高了可组合性。

  2. 参照透明。 引用透明的表达式将始终得出相同的结果。通过允许将相同的表达式彼此替换,并允许在不使用锁的情况下彼此独立地(即在不同线程上)计算表达式,从而提高了可组合性

  3. 不变性。不变对象的状态一旦创建便无法更改。这可以提高可组合性,因为您可以依靠对象的稳定值,而不必担心某些函数或对象在创建后是否改变了对象的状态。

  4. 纯度。纯函数没有副作用。它们只有一个输入和一个输出,这使它们更具可组合性,因为您可以将一个函数的输出放入另一个函数的输入中,而不必担心函数外部的某些内容是否已更改。

锁之所以不会构成组成部分,是因为它们是外部元素,将两个共享某个状态的操作组合在一起时,您必须依靠锁,并且出于各种原因,这些原因与使用锁固有的复杂性有关。

“单子不组成”这句话对我来说没有多大意义。monad的全部要点是采用一些有状态的东西(例如键盘输入或屏幕输出),并将其转变为更纯净的数学形式,实际上更易于组合。


4
我认为stackoverflow.com/questions/7040844/…很好地解释了“单子不组成”的含义,尽管我同意单子比锁更容易组合。
Ixrec 2015年

您对“参照透明度”和“纯度”的要点实际上是对纯度的两个要求。应避免使用术语“参照透明性”,因为它定义不明确
BlueRaja-Danny Pflughoeft 2015年

1
单子是具有某些运算的代数结构。您在最后一段中描述的是IO捕获诸如键盘输入之类的“状态操作” 的类型。IO类型的值的确可以组成,但是整个类型 IO是单子。这种类型不能与其他单子类型(例如列表类型)组合。也就是说,我们不能系统地产生一种类型IO . List,其行为就像两个 IOList同时进行。那有意义吗?我不确定我解释得很好。
Tikhon Jelvis
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.