Haskell模式匹配"发散"和⊥

时间:2013-02-05 00:53:44

标签: haskell pattern-matching

我试图理解Haskell 2010 Report section 3.17.2“模式匹配的非正式语义”。大多数情况下,与模式匹配成功或失败相关似乎都很简单,但是我很难理解被描述为模式匹配“发散”的情况。

我半说服它意味着匹配算法没有“收敛”到答案(因此匹配函数永远不会返回)。但是,如果不返回,那么,它如何返回一个值,如括号“即返回”所示?无论如何“返回”意味着什么?一个人如何处理这个结果?

第5项具有特别令人困惑的(对我而言)“如果值为,则匹配发散”。这只是说的值会产生的匹配结果吗? (撇开我不知道那个结果意味着什么!)

任何照明,可能有一个例子,将不胜感激!


经过几个冗长的回答后补遗: 谢谢Tikhon和所有人的努力。

似乎我的困惑来自于有两个不同的解释领域:Haskell特征和行为的领域,以及数学/语义领域,而在Haskell文献中,这两个是混合在一起试图用术语来解释前者后者,没有足够的路标(对我来说)属于哪个元素。

显然“bottom”位于语义域中,并且不作为Haskell中的值存在(即:您无法输入,您永远不会得到打印出来的结果为“{{ 1}}“)。

因此,在解释说函数“返回”的地方,这指的是执行任何一些不方便的事情的函数,例如不终止,抛出异常或返回“未定义”。是吗?

此外,那些评论实际一个可以传递的值的人,实际上是在考虑绑定到尚未被实际评估的普通函数(可以说是“未爆炸的炸弹”)并且可能永远不会因为懒惰而对吗?

2 个答案:

答案 0 :(得分:16)

值为⊥,通常发音为“bottom”。它是语义上的一个值 - 它不是正常的Haskell值本身。它表示不产生正常Haskell值的计算:例如异常和无限循环。

语义是关于定义程序的“含义”。在Haskell中,我们通常谈论指称语义,其中值是某种数学对象。最简单的例子是表达式10(以及表达式9 + 1)具有 number 10的表示(而不是 Haskell值 10)。我们通常写⟦9 + 1⟧ = 10意味着Haskell表达式9 + 1的表示是数字10。

但是,我们如何处理像let x = x in x这样的表达式?此表达式没有Haskell值。如果你试图评估它,它将永远不会完成。而且,这对应于什么数学对象并不明显。但是,为了推理程序,我们需要给它一些表示。所以,基本上,我们只是为所有这些计算组成一个值,我们称之为值bottom(底部)。

所以⊥只是一种定义不返回的计算“意味着”的方法。

我们还将undefinederror "some message"等其他计算定义为,因为它们也没有明显的正常值。所以抛出异常对应。这正是模式匹配失败时的情况。

通常的思考方式是每个Haskell类型都被“解除” - 它包含。也就是说,Bool对应{⊥, True, False}而非{True, False}。这表示Haskell程序不能保证终止并且可以有例外。定义自己的类型时也是如此 - 类型包含您为其定义的每个值以及

有趣的是,由于Haskell不严格,可以存在于普通代码中。所以你可以得到像Just ⊥这样的值,如果你从来没有评估它,一切都会正常工作。一个很好的例子是constconst 1 ⊥评估为1。这适用于失败的模式匹配:

const 1 (let Just x = Nothing in x) -- 1

您应该阅读Haskell WikiBook中denotational semantics的部分。这是一个非常平易近人的介绍,我个人觉得非常有趣。

答案 1 :(得分:11)

指称语义

因此,简单的指称语义,即所在的位置,是从Haskell值到某些其他值空间的映射。你这样做是为了以更正式的方式赋予程序意义,而不仅仅是讨论程序应该做什么 - 你说它们必须尊重它们的指称语义。

因此,对于Haskell,您经常会想到Haskell表达式如何表示数学值。您经常会看到Strachey括号⟦·⟧来表示从Haskell到Math的“语义映射”。最后,我们希望我们的语义括号与语义操作兼容。例如

⟦x + y⟧ = ⟦x⟧ + ⟦y⟧

左侧+是Haskell函数(+) :: Num a => a -> a -> a,右侧是交换组中的二进制运算。虽然很酷,但因为我们知道我们可以使用语义映射中的属性来了解我们的Haskell函数应该如何工作。也就是说,让我们在“数学”中写下交换属性

  ⟦x⟧ + ⟦y⟧ == ⟦y⟧ + ⟦x⟧ 
= ⟦x + y⟧ == ⟦y + x⟧ 
= ⟦x + y == y + x⟧

其中第三步也表明Haskell (==) :: Eq a => a -> a -> a应该具有数学等价关系的属性。


好吧,除了......

无论如何,这一切都很好,直到我们记住计算机是有限的东西而数学并不关心那些(除非你使用直觉逻辑,然后你得到Coq)。所以,我们必须注意我们的语义不遵循Math的地方。以下是三个例子

⟦undefined⟧         = ??
⟦error "undefined"⟧ = ??
⟦let x = x in x⟧    = ??

这是发挥作用的地方。我们只是声称,就Haskell的指称语义而言,每个例子都可能意味着(新引入的数学/语义概念)的数学属性是什么?好吧,这就是我们开始真正深入了解语义域并开始讨论函数和CPO等的单调性的地方。但基本上,是一个数学对象,它与非终止游戏的游戏大致相同。从语义模型的角度来看,是有毒的,它以其毒性 - 非确定性来感染表达。

但它不是Haskell语言的概念,只是一种语言域的Haskell语言。在Haskell中,我们有undefinederror和无限循环。这很重要。


超语义行为(旁注)

因此,一旦我们理解了⟦undefined⟧ = ⟦error "undefined"⟧ = ⟦let x = x in x⟧ = ⊥的数学意义,的语义就会清晰,但同样清楚的是,每个人在现实中都有不同的效果。这有点像C的“未定义行为”......就语义域而言,它的行为是未定义的。你可能会在语义上称它为不可观察的。


那么模式匹配如何返回

那么返回是什么意思“语义上”?好吧,是一个完全有效的语义值,它具有模拟非确定性(或异步错误抛出)的感染属性。从语义的角度来看,它是一个完全有效的值,可以按原样返回。

从实现的角度来看,您有许多选择,每个选择都映射到相同的语义值。 undefined不太正确,也没有进入无限循环,所以如果你要选择一个语义上未定义的行为,你也可以选择一个有用的并抛出错误

*** Exception: <interactive>:2:5-14: Non-exhaustive patterns in function cheers