简体   繁体   English

为什么内置函数应用于被认为是弱头正常形式的太少参数?

[英]Why is a built-in function applied to too few arguments considered to be in weak head normal form?

The Haskell definition says: Haskell 定义说:

An expression is in weak head normal form (WHNF), if it is either: 表达式是弱头正常形式(WHNF),如果它是:

  • a constructor (eventually applied to arguments) like True, Just (square 42) or (:) 1 一个构造函数(最终应用于参数),如True,Just(square 42)或(:) 1
  • a built-in function applied to too few arguments (perhaps none) like (+) 2 or sqrt. 一个内置函数应用于太少的参数(可能没有),如(+)2或sqrt。
  • or a lambda abstraction \\x -> expression. 或lambda抽象\\ x - >表达式。

Why do built-in functions receive special treatment? 为什么内置功能会得到特殊处理? According to lambda calculus, there is no difference between a partially applied function and any other function, because at the end we have only one argument functions. 根据lambda演算, 部分应用函数和任何其他函数之间没有区别,因为最后我们只有一个参数函数。

A normal function applied to an argument, like the following: 应用于参数的常规函数​​,如下所示:

(\x y -> x + 1 : y) 1

Can be reduced, to give: 可以减少,给予:

\y -> 1 + 1 : y

In the first expression, the "outermost" thing was an application, so it was not in WHNF. 在第一个表达式中,“最外层”的东西是一个应用程序,所以它不在WHNF中。 In the second, the outermost thing is a lambda abstraction, so it is in WHNF (even though we could do more reductions inside the function body). 在第二个中,最外层的东西是lambda抽象,所以它在WHNF中(即使我们可以在函数体内做更多的缩减)。

Now lets consider the application of a built-in (primitive) function: 现在让我们考虑一下内置(原始)函数的应用:

(+) 1

Because this is a built-in, there's no function body in which we can substitute 1 for the first parameter. 因为这是一个内置函数,所以我们没有函数体可以用1代替第一个参数。 The evaluator "just knows" how to evaluate fully "saturated" applications of (+) , like (+) 1 2 . 评估者“只知道”如何评估(+)完全“饱和”应用,如(+) 1 2 But there's nothing that can be done with a partially applied built-in; 部分应用的内置功能无法实现; all we can do is produce a data structure describing "apply (+) to 1 and wait for one more argument", but that's exactly what the thing we're trying to reduce is . 我们所能做的是产生描述“应用(+)为1,等待一个多参数”的数据结构,而这正是我们试图减少就是 So we do nothing. 所以我们什么都不做。

Built-ins are special because they're not defined by lambda calculus expressions, so the reduction process can't "see inside" their definition. 内置函数是特殊的,因为它们不是由lambda演算表达式定义的,因此缩减过程不能“看到”它们的定义。 Thus, unlike normal functions applications, built-in function applications have to be "reduced" by just accumulating arguments until they are fully "saturated" (in which case reduction to WHNF is by running whatever the magic implementation of the built-in is). 因此,与普通函数应用程序不同,内置函数应用程序必须通过累积参数来“减少”,直到它们完全“饱和”(在这种情况下,通过运行内置的任何神奇实现来减少WHNF) 。 Unsaturated built-in applications cannot be reduced any further, and so are already in WHNF. 不饱和的内置应用程序无法进一步减少,因此已经在WHNF中。

Consider 考虑

Prelude> let fn = [(+x) | 前奏>让fn = [(+ x)​​| x <- [1..]] !! x < - [1 ..]] !! n ñ
Prelude> let g = f 20000000 :: Int -> Int 前奏>让g = f 20000000 :: Int - > Int

g is at this point not in WHNF! g此时不在WHNF! You can see this by evaluating, say, g 3 , which takes a noticable lag because you need WHNF before you can apply an argument. 您可以通过评估g 3来看到这一点,因为在应用参数之前需要WHNF,因此需要显着滞后。 That's when the list is traversed in search for the right built-in function. 这是在搜索正确的内置函数时遍历列表的时候。 But afterwards, this choice is then fixed, g is WHNF (and indeed NF: that's the same for lambdas, perhaps what you meant with your question) and thus any subsequent calls will give a result immediately. 但之后,这个选择被修复了, g是WHNF(事实上NF:对于lambdas也是如此,也许你对你的问题意味着什么),因此任何后续调用都会立即给出结果。

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

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