就像标题中所说的那样:对Haskell函数返回单元进行评估有什么保证?有人会认为在这种情况下无需运行任何类型的评估,()
除非存在明确的严格性要求,否则编译器可以将所有此类调用替换为立即值,在这种情况下,代码可能必须决定是否应返回()
或底部。
我已经在GHCi中对此进行了实验,似乎发生了相反的情况,也就是说,似乎正在评估这种功能。一个非常原始的例子是
f :: a -> ()
f _ = undefined
f 1
由于存在,评估会引发错误undefined
,因此肯定会发生某些评估。但是,尚不清楚评估的深度。有时它看起来像需要评估返回函数的所有调用一样深入()
。例:
g :: [a] -> ()
g [] = ()
g (_:xs) = g xs
如果使用,此代码将无限循环g (let x = 1:x in x)
。但是之后
f :: a -> ()
f _ = undefined
h :: a -> ()
h _ = ()
可用于显示h (f 1)
return ()
,因此在这种情况下,并非所有单位值的子表达式都被求值。这里的一般规则是什么?
ETA:我当然知道懒惰。我在问什么阻止编译器编写者使这种特殊情况变得比平时更懒。
ETA2:示例摘要:GHC似乎与()
任何其他类型完全一样,即,似乎存在一个问题,即应该从函数中返回驻留该类型的哪个常规值。优化算法似乎并没有滥用这样一个值的事实。
ETA3:当我说Haskell时,我的意思是报告定义的Haskell,而不是GHC中的Haskell。似乎是一个假设没有像我想象的那样广泛共享(这是“ 100%的读者”),或者我可能能够提出一个更明确的问题。即便如此,我还是很遗憾更改问题的标题,因为它最初询问要为此类函数调用提供什么保证。
ETA4:这个问题似乎已经解决了,我认为这个问题没有得到解决。(我一直在寻找一个“封闭式问题”功能,但只找到了“回答您自己的问题”,由于无法回答,所以我没有走这条路线。)没有人从报告中提出任何决定该问题的方式,我很想将其解释为有力但不确定的“不能保证如此语言”的答案。我们所知道的是,当前的GHC实施不会跳过对该功能的评估。
将OCaml应用程序移植到Haskell时遇到了实际问题。原始应用程序具有多种类型的相互递归结构,并且代码assert_structureN_is_correct
在1..6或7中声明了许多要求N 的函数,如果结构确实正确,则每个函数都返回单位;如果结构不正确,则返回异常。 。另外,这些函数在分解正确性条件时会相互调用。在Haskell中,使用Either String
monad 可以更好地解决此问题,因此我以这种方式进行了转录,但是作为理论问题仍然存在。感谢您的所有输入和回复。
f 1
被“替换” undefined
。
... -> ()
可以1)终止并返回()
,2)在发生异常/运行时错误时终止并且无法返回任何内容,或者3)求差(无限递归)。GHC不会优化代码,前提是只会发生1):如果f 1
有要求,它不会跳过评估并返回()
。Haskell语义是对其进行评估,并查看1,2,3之间会发生什么。
()
(类型或值)。如果您将其替换() :: ()
为0 :: Int
无处不在,则会发生所有相同的观察。这些都是懒惰评估的无聊的旧结果。
()
的类型,()
和undefined
。
h1::()->() ; h1 () = ()
和h2::()->() ; h2 _ = ()
。同时运行h1 (f 1)
和h2 (f 1)
,看到只有第一个需求(f 1)
。