我是Haskell的初学者,undefined
函数的类型签名使我大吃一惊。
我期望有一些更简单的方法,但是我在Hackage上发现了这一点:
undefined :: forall (r :: RuntimeRep). forall (a :: TYPE r). HasCallStack => a
错误的特殊情况。预计编译器将识别出这种情况并插入更适合出现
undefined
的上下文的错误消息。
能否请您解释一下此签名的含义?
谢谢!
答案 0 :(得分:5)
对于初学者需要知道的所有方面,签名都是
undefined :: a
这意味着,与类型变量(即,任何小写字母)一样,a
是universally quantified,也可以使其明确:
{-# LANGUAGE ExplicitForall #-}
undefined :: forall a. a
...或者,我更喜欢写它
{-# LANGUAGE ExplicitForall, UnicodeSyntax #-}
undefined :: ∀ a. a
推断量化是针对所有类型,即所有类型为*
的事物(阅读:“类型”,更准确的是提升类型的类型 > –解除含义,可以是懒惰的重击)。因此,无论需要什么类型,都可以在任何表达式中使用undefined
。
现在,undefined
当然是类似“部分函数”的东西,基本上是一个零参数的函数,该参数在任何地方都没有定义。 (FTR,它不是 函数,因为根据定义,该函数具有 参数。)
您希望在实际评估时得到一条有用的错误消息,但是GHC默认情况下不会为所有内容生成调用堆栈(出于性能原因),因此它曾经错误消息几乎完全无用的情况。这就是HasCallStack
出现的地方:这是一个约束,它实际上告诉某些代码可能在其中发生的上下文undefined
,它应该记下发生的位置,以便错误消息可以实际显示出来起来所以,
undefined :: ∀ a. HasCallStack => a
在HasCallStack
之后出现∀ a
有点令人困惑-这实际上与a
没有任何关系,但是与undefined
将使用。只是签名的形式总是
Identifier :: Quantifiers. Constraints => Type
和HasCallStack
是一个约束,这就是为什么它出现在中间的原因。 (通常,约束实际上适用于您已量化的类型变量之一。)
最后,这些RunTimeRep
内容是关于高度多态性的。我本人并不太了解,但是Why is the undefined function levity-polymorphic when using it with unboxed types?
答案 1 :(得分:5)
这是@leftaroundabout答案的延续。
在Haskell中,值具有类型。但是类型自己也有类型。当一种类型充当另一种类型的类型时,我们称其为“种类”。
在Haskell中最重要和最常见的一种是Type
,通常在签名中表示为*
。这是一种“提升”的类型,也就是说,其值可以是杂项,在评估时可以发散,抛出错误等。例如,类型Int
的类型为{{1 }}。
还有其他类型,例如Int#
不会被 取消。类型为Type
的值从不是一个笨拙的东西,它始终是内存中的实际值。
简而言之,值在内存中的表示形式受其类型类型的控制。
RuntimeRep
是另一种。它是Int#
和LiftedRep
之类的类型。我们将看到,这些类型没有任何值,仅存在于express things at the type level中。
有一个称为TYPE
的超魔术类型级实体,当使用类型IntRep
(即描述内存中表示的类型)进行参数化时,该实体将返回该类型其值具有该表示形式的类型。例如,RuntimeRep
是Type
,而TYPE LiftedRep
的种类是Int#
。
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
具有如此奇怪的签名的原因。问题是,我们希望能够在 all 函数中使用undefined
,既可以返回类型undefined
类型的函数,又可以返回类型{ {1}}(换句话说:Type
类型)或返回另一个未提升类型的函数。否则,我们将需要TYPE IntRep
的多个不同版本,这很烦人。
解决方案是使Int#
高度多态。签名说:对于任何可能的内存表示形式(undefined
)和任何值具有该表示形式的 type ,undefined
都会计算该类型的成员。>