[英]What does type signature for `undefined` mean in Haskell?
我是Haskell的初学者,我对undefined
函数的类型签名感到吃惊。
我期待更简单的东西,但我在Hackage上发现了这个:
undefined :: forall (r :: RuntimeRep). forall (a :: TYPE r). HasCallStack => a
一个特殊的错误案例。 预计编译器将识别这一点并插入更适合于出现
undefined
的上下文的错误消息。
你能解释一下这个签名是什么意思吗?
谢谢!
对于初学者需要知道的所有问题,签名很简单
undefined :: a
这意味着,与通常使用类型变量(即任何小写字母)一样, a
是普遍量化的 ,也可以是明确的:
{-# LANGUAGE ExplicitForall #-}
undefined :: forall a. a
......或者,我喜欢写它
{-# LANGUAGE ExplicitForall, UnicodeSyntax #-}
undefined :: ∀ a. a
量化被认为是所有类型的 ,即所有类型的东西*
(读:“类型”,更准确的类型提升类型 - 提升意味着它可以是懒惰的thunk)。 因此,无论何种类型需要,您都可以在任何表达式中使用undefined
。
现在, undefined
当然是一个“部分函数”之类的东西,基本上是一个无处定义的零参数的函数。 (FTR,它不是一个函数,因为定义函数有参数[s]。)
您希望在实际评估时获得有用的错误消息,但GHC默认情况下不会为所有内容生成调用堆栈(出于性能原因),因此过去的情况是错误消息几乎完全无用。 这就是HasCallStack
用武之地:这是一个约束,它实质上告诉了某些代码可能会发生undefined
的上下文,它应该注意它发生的位置,以便错误消息实际显示出来。 所以,
undefined :: ∀ a. HasCallStack => a
这是一个有点令人困惑的是, HasCallStack
后出现∀ a
-这并不真的有什么关系a
但在这背景下undefined
将被使用。 只是,签名的形式总是如此
:: . =>
和HasCallStack
是一个约束,这就是它出现在中间的原因。 (更常见的情况是,约束实际上适用于您量化的其中一个类型变量。)
最后,这个RunTimeRep
东西是关于levity多态的 。 我自己并不是真的了解它,但是在将未使用的类型与未装箱的类型一起使用时 , 为什么未定义的函数是levity-polymorphic?
这是@ leftaroundabout答案的延续。
在Haskell中,值具有类型。 但类型本身也有类型。 当一个类型作为另一种类型的类型时,我们将其称为“种类”。
Haskell中最重要和最常见的类型是Type
,通常在签名中表示为*
。 它是那种“被提升”的类型,也就是说,它的值可以是thonks,当被评估时,可以发散,抛出错误等等......例如Int
类型有Type
。
还有其他类型,如Int#
, 没有解除。 Int#
类型的值永远不是thunk,它始终是内存中的实际值。
总之,值的内存中表示由它们的类型的种类控制的 。
RuntimeRep
是另一种。 它是LiftedRep
和IntRep
等类型。 这些类型没有任何值,它们仅仅是为了在类型级别表达事物 ,我们将会看到。
有一个名为TYPE
的超级魔法类型级实体,当使用类型RuntimeRep
(具有描述内存中表示的类型)进行参数化时,返回其值具有该表示的类型。 例如, Type
是TYPE LiftedRep
,而Int#
的TYPE IntRep
是TYPE IntRep
。
ghci> :set -XMagicHash
ghci> import GHC.Prim
ghci> import GHC.Types
ghci> import Data.Kind
ghci> :kind (Int :: TYPE 'LiftedRep)
(Int :: TYPE 'LiftedRep) :: *
ghci> :kind Int#
Int# :: TYPE 'IntRep
现在我们可以回到为什么undefined
有这么奇怪的签名。 问题是,我们希望能够在所有函数中使用undefined
,无论是返回类型Type
函数,还是返回TYPE IntRep
(换句话说: Int#
类型)或返回的函数另一种未提升的类型。 否则,我们需要多个不同版本的undefined
,这会很烦人。
解决方案是使undefined
levity-polymorphic 。 签名表示:对于任何可能的内存中表示( RuntimeRep
)以及其值具有该表示的任何可能类型 , undefined
计算该类型的成员。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.