表达的“最外部”在Haskell中是什么意思

时间:2018-07-08 20:21:11

标签: haskell

这里是真正的初学者,我正在阅读有关NF和WHNF之间的区别以及我遇到过的州的定义

  

要确定表达式是否为弱头正态形式,我们只需要       看一下表达式的最外层部分。

我不确定要确定“最外层”部分的适用标准。例如(来自@hammer的堆栈溢出答案):

setTimeout(function() {locked = true;}, 0)

特别是在第一个示例中,(:)运算符位于'h'和另一个表达式的中间,那么它的最外面部分是什么?

通常,在查看表达式时,如何确定最外面的部分?

2 个答案:

答案 0 :(得分:7)

好问题。在这里,“最外面的”(或“最上面的”)描述了位置的一种形式,表示该形式的标准抽象视图可能与其实际语法有所不同。例如,这两个表达式:

(1, 2)
(,) 1 2

在Haskell中具有相同的含义。事实证明,在两种情况下,即使表达式的句法形式不同且逗号在语法中的不同物理位置出现,构造函数(,)都是表达式的最外层部分。

通常,Haskell的“标准语法”涉及以下形式的函数应用:

fexpr expr1 .. exprn

但是,该语言还允许其他类型的语法:

1 + 2                -- infix operators
(3, 4)               -- tuples
[5,6,7,8]            -- lists
"abc"                -- strings

这些备用语法可以转换为标准语法,如下所示:

1 + 2   ==>   (+) 1 2
(3, 4)  ==>   (,) 3 4
[5,6,7,8]   ==>  (:) 5 ((:) 6 ((:) 7 ((:) 8 [])))
"abc"   ==>   (:) 'a' ((:) 'b' ((:) 'c' []))

(+)虽然很明显,但它是一个变量,其值是一个函数(例如sqrt);而(,)(:)是构造函数(就像TrueJust一样)。即使[1,2,3]是特殊语法,但更令人困惑的是,空列表[]是一个(一元)构造函数!这就是为什么我在标准语法版本的右侧仍然使用空列表。

无论如何,一旦转换为标准语法,表达式将成为构造函数应用程序,就像其中之一:

True               -- a nullary constructor
(,) (1+2) (2+3)    -- constructor expecting two args and fully applied
(:) 5              -- constructor partially applied and expecting one more arg

我们说表达式的“最外层部分”是此构造函数应用程序,否则它将是未应用的lambda抽象:

(\x y -> (+) x (length y))

我们说表达式的“最外部分”是这种未应用的lambda抽象,否则将是其他一些东西:

w                    -- a variable
(\x -> x) 10         -- an applied lambda abstraction
(f x) y ((*) 2 z)    -- some other function application
(+) 10 (length (1:[]))  -- another function application

我们说表达式的“最外面的部分”是变量引用或函数应用程序等等。

无论如何,如果最外面的部分是构造函数应用程序或未应用的lambda抽象,那么据说它是弱头法线形式。如果还有其他事情,那就不是。

因此,Just (5+6)在WHNF中,因为最外面的部分是构造函数Just的应用程序。另一方面,sqrt (5+6)在WHNF中不是不是,因为最外面的部分是变量sqrt的应用,而变量不是构造函数。

类似地,在WHNF中5+6本身不是不是,因为最外面的部分是将变量(+)应用于56,而[5,6] 在WHNF中是因为最外面的部分是(暗示的)构造函数(:)5[6]上的应用。

答案 1 :(得分:2)

您必须查看抽象语法树以了解其含义。

{{1}}

“最外层”是指树的根。