编写指称语义映射函数有什么用?

时间:2013-10-15 20:12:03

标签: haskell formal-semantics denotational-semantics

我对指称语义的概念有点困惑。据我所知,指称语义应该描述函数和表达式如何在特定的编程语言中工作。用于描述这些功能以及它们如何工作的正确形式究竟是什么?究竟什么是“域”,以及如何构建映射函数?

作为一个例子,“做X同时Y”的映射函数是什么?

我一直在网上阅读大量资料,但这很难理解。这些描述是否类似于无上下文语法?

请让我知道,谢谢!

1 个答案:

答案 0 :(得分:20)

将外延视为从语法到“意义”的映射。您可能会看到它用双括号编写,因此您可以将[[3]] = 3读作“语法的表示[数字3]是数字3”。

一个简单的例子就是算术。通常你有一个像

这样的外延
[[x + y]] = [[x]] + [[y]]

左边的+是一个语法加号,而右边的+是算术加号。为了更清楚,我们可能会改为lispy语法。

[[(+ x y)]] = [[x]] + [[y]]

现在要问的一个非常重要的问题是这个映射的范围(codomain)是什么?到目前为止,我一直认为将其视为“数字和加法生活的一些肮脏的域名”已经足够了,但这可能是不够的。重要的是,您的示例将快速打破它。

[[do X while True]] = ???

因为我们不一定有一个包含非终止概念的mathy域名。

在Haskell中,这可以通过将数学域称为“提升”域或CPO域来解决,该域实质上直接添加非终止。例如,如果您的未提升域是整数I,则提升的域名为⊥ + I,其中称为“底部”,表示非终止。

这意味着我们可以编写(使用Haskell语法)

[[let omega = 1 + omega in omega]] = ⊥

动臂。我们有意义 - 无限循环的意义是......什么都没有!

Haskell中提升域的技巧是因为Haskell是懒惰的(非严格的),所以可能会有数据类型和的有趣交互。例如,如果我们有type IntList = Cons Int IntList | Nil,则IntList上的提升域直接包含(一个完整的无限循环)以及Cons ⊥ ⊥之类尚未完全解析的内容,但提供的信息比普通的更多。

我故意写下“更多信息”。 CPO形成“定义”的部分订单(即PO)。 最大程度上未定义,因此对于CPO中的任何其他内容都是<=。然后你得到像Cons ⊥ ⊥ <= Cons 3 ⊥这样的东西,它们按照你的部分顺序形成一个链。您经常会说,x <= y如果y包含的信息多于x“或”y的定义比x更多“。

对我而言,最重要的一点是,通过在我们的表示域中定义这种CPO结构,我们可以非常准确地谈论严格和非严格评估之间的差异。在严格的语言中(或者实际上,在您的语言可能有或可能没有的严格域中),您的CPO都是“平坦的”,因为您要么具有完全定义的结果,要么而没有其他任何内容。当您的CPO不平坦时,就会发生懒惰。

另一个重点是“你不能在底部进行模式匹配”的概念......如果我们将底部视为无限循环(尽管使用这个新的抽象模型,它不会拥有< / em>表示......例如,它可能是一个段错误)然后这句格言只不过是表达停顿问题的另一种方式。结果是,如果x <= y然后f x <= f y,那么所有合理的功能必须是“单调的”。如果你花费一些时间来处理这个概念,你会发现它会使那些具有不同非底层行为的函数无论其参数是否为底。例如,停止神谕是非单调的

halting (⊥) = False     -- we can't pattern match on bottom!
halting _   = True

但是“破碎的神谕”是

hahahalting (⊥) = ⊥     -- we're still pattern matching, 
                            -- but at least the behavior is right
hahahalting _   = True

我们使用seq

撰写
hahahalting x = x `seq` True    -- valid Haskell

这也带来了明显的缓解the dangers of non-monotonic functions, like Haskell's spoon。我们可以通过利用表面上不合理的异常捕获来编写它们......但是如果我们不小心它会导致非常不稳定的行为。

你可以从指称语义中学到更多东西,所以我将提供关于指称语义的Edward Z. Yang's notes