繁体   English   中英

'bottom' (⊥) 在 Haskell 函数定义中的作用是什么?

[英]What is the role of 'bottom' (⊥) in Haskell function definitions?

我不明白bottom_|_ )在 Haskell 函数定义中所扮演的角色。

例如zip的定义将其描述为“正确的懒惰”,因为

zip [] _|_ = []

但我不清楚这与

zip [] _ = []

_|_在上述函数定义中扮演什么角色? 特别是,它与使用_有何不同?


更新和注意:正如优秀答案的读者会自己发现的那样,这些答案的一个关键部分,值得在这里提出,是没有(并且不能),事实上,出现在 Haskell 函数定义中 继续阅读

底部本质上是说undefined的奇特代数方式。

如果你试试这个,你就会明白为什么zip的右手参数是懒惰的:

λ> zip [] undefined
[]
λ> zip undefined []
*** Exception: Prelude.undefined

这是因为undefined只有在您尝试对其进行评估时才会失败。

由于它的呈现方式,您可能会将_|__混淆。 我会清楚:行zip [] _|_ = []作为模式匹配而公式,说明平等zip [] _|_[] 也就是说,这不是有效的 Haskell 代码,而是一种表示“我不在乎第二个参数”的符号化、抽象代数方式。

zip的定义中,您当然可以使用_ ,但这无关紧要。 您可以使用任何名称,只要它不是构造函数匹配模式,例如(Just x)(a,b) 值将保持未计算状态,直到它们必须在纯代码中进行模式匹配。

您可以在此处阅读有关延迟评估的更多信息。

您可以在此处此处阅读有关底部的更多信息。

我认为 OP 已经意识到这一点,但为了其他同样困惑的人的利益: zip [] _|_ = []不是实际代码!

符号_|_ (这仅仅是一个数学符号的ASCII艺术渲染 )是指底部1,但只有当我们谈论哈斯克尔。 在 Haskell 代码中,它没有这个含义2

zip [] _|_ = []是对zip实际代码属性的描述; 如果您使用第一个参数[]调用它并将任何底部值作为第二个参数传递,则结果等于[] 他们之所以要这么说,是因为函数f不严格的技术定义是当f ⊥不是

但是在定义 Haskell 函数(在代码中)时,没有_|_ (或 ,或undefined ,或底部的概念)的作用。 它是不可能的模式匹配上的参数,看看它是否是 ,对于一些原因,所以不存在用于实际的符号在Haskell代码3。 zip [] _|_ = []是属性的文档,它是zip定义的结果,而不是其定义的一部分。

作为对这个属性的描述zip [] _ = []是一个不太具体的声明; 它会说无论你调用什么zip [] ,它都会返回[] 它相当于完全相同的东西,因为zip [] ⊥可以返回非底部的唯一方法是它根本不检查它的第二个参数。 但它对非严格性的定义没有那么直接。

由于构成函数zip [] _ = []定义的一部分的代码无法与zip [] _|_ = []进行比较和对比。 它们不是替代品,第一个是有效代码,第二个不是。


1这是永远运行、抛出异常或以其他方式计算为正常值的表达式的“值”。

2它甚至不是有效的 Haskell 标识符,因为它同时包含“namey”字符 ( _ ) 和“operator”字符 ( | )。 所以它实际上不能是 Haskell 代码中任何意义的符号!

3 undefined通常用于 ,但它更像是一个引用值的变量,而不是实际事物本身。 就像如果你有let xs = [1, 2, 3]你可以使用xs引用列表[1, 2, 3] ,但你不能将它用作匹配其他列表的模式; 尝试的模式匹配将被视为引入一个名为undefined的新变量或xs隐藏旧变量。

⊥ 出自数理序理论。 一个部分有序的集合有一个底部元素,表示为 ⊥,如果该元素在所有其他元素之前。 这如何进入 Haskell 文档? 在某个时候,计算机科学家意识到考虑计算机程序(无论使用何种语言)“意味着”是有用的。 一种方法称为指称语义。 在指称语义中,编程语言中的每个术语都被分配了一个“指称”或含义,在某些数学含义领域。 例如,如果能够说

  1. meaningInteger :: Integer -> mathematical integer
  2. meaningList :: [a] -> possibly-infinite sequence of elements of type a

不幸的是,这在 Haskell 中不太适用,因为例如,我可以写

oops :: Integer
oops = oops

这给了我一个Integer类型的术语,但没有合理的方法将其指定为数学整数的含义。 更有趣的是,我可以写这样的东西

undefined
undefined : undefined
3 : undefined
[undefined]
let foo = undefined : 3 : undefined : foo

这些都(可以)具有相同的类型,但具有各种不同级别的不确定性。 因此,我们需要将各种未定义的事物添加到我们的含义集合中。 但是,可以根据它们的定义对它们施加偏序 例如3 : 4 : []3 : 4 : undefined3 : 4 : undefined ,也比3 : undefined : 4更明确,但后两者没有可比性。 每种类型的底部元素,其定义最少的元素,称为 ⊥。

对 AJFarmar 的回答嗤之以鼻,我认为这个关键点没有明确说明:

  • _|_在 Haskell 代码中不是有效的文字或标识符!
  • 因此, zip [] _|_ = []也不是有效代码!

这隐含在 AJFarmar 这句话的意思中:

[T]他行zip [] _|_ = []不充当模式匹配,而是一个等式,说明zip [] _|_[]的相等性。

为了使它非常清晰, zip [] _|_ = []出现在zip定义的文档注释中。 它不是 Haskell 代码——它是用非正式的技术符号编写的英语注释,看起来有点像 Haskell 代码。 或者,换句话说,伪代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM