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

时间:2014-06-27 08:29:12

标签: haskell lambda-calculus reduction partial-application weak-head-normal-form

Haskell definition说:

  

表达式是弱头正常形式(WHNF),如果它是:

     
      
  • 一个构造函数(最终应用于参数),如True,Just(square 42)或(:) 1
  •   
  • 内置函数应用于太少的参数(可能没有),如(+)2或sqrt。
  •   
  • 或lambda abstraction \ x - >表达
  •   

为什么内置功能会受到特殊处理?根据lambda演算,部分应用函数和任何其他函数之间没有区别,因为最后我们只有一个参数函数。

2 个答案:

答案 0 :(得分:22)

应用于参数的正常函数,如下所示:

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

可以减少,给予:

\y -> 1 + 1 : y

在第一个表达式中,“最外层”的东西是一个应用程序,所以它不在WHNF中。在第二个中,最外层的东西是lambda抽象,所以它在WHNF中(即使我们可以在函数体内做更多的缩减)。

现在让我们考虑一下内置(原始)函数的应用:

(+) 1

因为这是一个内置函数,所以我们没有函数体可以用1代替第一个参数。评估员“只知道”如何评估(+)的完全“饱和”应用程序,如(+) 1 2。但是,使用部分应用内置功能无法做到任何事情;我们所能做的就是产生一个描述“应用(+)到1并等待一个参数”的数据结构,但这正是我们试图减少的事情 。所以我们什么都不做。

内置函数是特殊的,因为它们不是由lambda演算表达式定义的,因此缩减过程不能“看到”它们的定义。因此,与普通函数应用程序不同,内置函数应用程序必须通过累积参数来“减少”,直到它们完全“饱和”(在这种情况下,通过运行内置的任何神奇实现来减少WHNF) 。不饱和的内置应用程序无法进一步减少,因此已经在WHNF中。

答案 1 :(得分:3)

考虑

  

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

g此时不在WHNF中!你可以通过评估g 3来看到这一点,因为你需要WHNF然后才能应用一个参数,这需要一个明显的滞后。在搜索正确的内置函数时遍历列表时的情况。但之后,这个选择被修复,g是WHNF(事实上NF:对于lambdas来说是相同的,也许你对你的问题意味着什么),因此任何后续调用都会立即给出结果。