就像标题中所说的那样:对Haskell函数返回单元进行评估有什么保证?有人会认为在这种情况下无需运行任何类型的评估,()除非存在明确的严格性要求,否则编译器可以将所有此类调用替换为立即值,在这种情况下,代码可能必须决定是否应返回()或底部。
我已经在GHCi中对此进行了实验,似乎发生了相反的情况,也就是说,似乎正在评估这种功能。一个非常原始的例子是
f :: a -> ()
f _ = undefined
Run Code Online (Sandbox Code Playgroud)
f 1由于存在,评估会引发错误undefined,因此肯定会发生某些评估。但是,尚不清楚评估的深度。有时它看起来像需要评估返回函数的所有调用一样深()。例:
g :: [a] -> ()
g [] = ()
g (_:xs) = g xs
Run Code Online (Sandbox Code Playgroud)
如果使用,此代码将无限循环g (let x = 1:x in x)。但是之后
f :: a -> ()
f _ = undefined
h :: a -> ()
h _ = ()
Run Code Online (Sandbox Code Playgroud)
可用于显示h (f 1)return (),因此在这种情况下,并非所有单位值的子表达式都被求值。这里的一般规则是什么?
ETA:我当然知道懒惰。我在问什么阻止编译器编写者使这种特殊情况变得比平时更懒。
ETA2:示例摘要:GHC似乎与()任何其他类型完全一样,即,似乎存在一个问题,即应该从函数返回该类型的哪个正则值。优化算法似乎并没有滥用这样一个值的事实。
ETA3:当我说Haskell时,我的意思是报告定义的Haskell,而不是GHC中的Haskell。似乎是一个假设没有像我想象的那样广泛共享(这是“ 100%的读者”),或者我可能能够提出一个更明确的问题。即便如此,我还是很遗憾更改了问题的标题,因为它最初询问对调用此函数有什么保证。
以下函数计算斐波那契数列:
fib = 0 : 1 : (zipWith (+) fib (tail fib))
Run Code Online (Sandbox Code Playgroud)
如果运行它,我们将得到一个无限列表,但是递归如何工作?如果函数不断调用自身,为什么会在屏幕上打印数字?如果您能解释编译器如何管理调用,将不胜感激。