()
类型有两个值,分别为()
和底部。如果您有一个表达式e :: ()
,实际上没有检查它的必要,因为它要么是e = ()
,要么通过检查它,您会崩溃一个本来不会崩溃的程序。因此,我认为对于
()
类型的值的操作不会检查该值,并且不会区分()
和底部之间的差异。然而,这是完全不正确的:
▎λ ghci
GHCi, version 9.0.2: https://www.haskell.org/ghc/ :? for help
ghci> u = (undefined :: ())
ghci> show u
"*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries/base/GHC/Err.hs:75:14 in base:GHC.Err
undefined, called at <interactive>:1:6 in interactive:Ghci1
ghci> () == u
*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries/base/GHC/Err.hs:75:14 in base:GHC.Err
undefined, called at <interactive>:1:6 in interactive:Ghci1
ghci> f () = "ok"
ghci> f u
"*** Exception: Prelude.undefined
CallStack (from HasCallStack):
error, called at libraries/base/GHC/Err.hs:75:14 in base:GHC.Err
undefined, called at <interactive>:1:6 in interactive:Ghci1
这是什么原因呢?以下是一些猜测:
出于某种我想不到的原因,在
()
上不懒惰可能是有用的。有时我们想要让底部传播。Haskell 的语义是以这样的方式编写的:解构任何 ADT,甚至是微不足道的 ADT,都会检查它们。这意味着,使用
case (undefined :: ()) of { () -> ... }
不会抛出异常,这将违反语言语义()
是一种极其特殊的情况,在像 Haskell 这样的大型语言中,没有必要关注如何挤出这个微小的额外的安全性还有一个可能的组合解释,即 Haskell 可能已经有了规定表达式
case e of
在检查除类型为()
之外的e
时的语义,但这可能会污染相对较低的收益的语言规范
()
的底部几乎总是程序员错误的指示,因此不检查它将违反“快速失败”的原则。这是一个有趣的观点。 - Quelklef