为什么不进行以下类型检查? _
的类型被推断为Double。
{-# LANGUAGE ScopedTypeVariables, Rank2Types #-}
module Main (main) where
data D a = D a
main =
let
n = D (1 :: forall a. (Floating a) => a)
in
case n of
D (_ :: forall a. (Floating a) => a) -> return ()
答案 0 :(得分:4)
您期望n
的类型似乎是D (forall a. (Floating a) => a)
,但这显然是不推断的类型。实际上,如果您尝试将该类型注释添加到n
,您会发现GHC会大声抱怨。这种类型需要GHC支持不可预测的多态性,而目前它并不支持(有关它是什么以及它为何复杂的更多信息,请参阅What is predicativity?)。
n
实际推断的类型是D Double
。这实际上是两件事情的结果:可怕的monomorphism restriction和Haskell的类型默认规则。由于单同性限制,n
必须推断为单态类型(因为它在语法上不是函数,并且没有显式类型注释)。出于这个原因,D 1
将是不明确的,因为1 :: forall a. (Floating a) => a
是多态的。但是,在这种情况下,Haskell对数值类型有默认规则,主要是为了避免因Haskell的多态数字文字而解决歧义。
由于您已明确向1
添加了类型注释以使其成为Floating
,因此Haskell将其默认规则应用于浮点类型,默认值为Double
。因此,n
的类型推断为D Double
。
如果禁用单态限制,则n
的类型将是稍微更有趣的类型forall a. Floating a => D a
,但这是更简单的通用量化类型,而不是您想要的存在量化类型。