这里是真正的初学者,我正在阅读有关NF和WHNF之间的区别以及我遇到过的州的定义
要确定表达式是否为弱头正态形式,我们只需要 看一下表达式的最外层部分。
我不确定要确定“最外层”部分的适用标准。例如(来自@hammer的堆栈溢出答案):
setTimeout(function() {locked = true;}, 0)
特别是在第一个示例中,(:)运算符位于'h'和另一个表达式的中间,那么它的最外面部分是什么?
通常,在查看表达式时,如何确定最外面的部分?
答案 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
);而(,)
和(:)
是构造函数(就像True
或Just
一样)。即使[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
本身不是不是,因为最外面的部分是将变量(+)
应用于5
和6
,而[5,6]
是在WHNF中是因为最外面的部分是(暗示的)构造函数(:)
在5
和[6]
上的应用。
答案 1 :(得分:2)
您必须查看抽象语法树以了解其含义。
{{1}}
“最外层”是指树的根。