Haskell 模式匹配推断类型

Haskell 模式匹配推断类型,haskell,pattern-matching,higher-rank-types,Haskell,Pattern Matching,Higher Rank Types,为什么下面的类型不检查?_u的类型被推断为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) ->

为什么下面的类型不检查?_u的类型被推断为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 ()

对于所有a,您期望n的类型似乎都是D。浮动a=>a,但这显然不是推断的类型。事实上,如果您尝试将该类型注释添加到n中,您会发现GHC会大声抱怨。这种类型需要GHC支持非指示性多态性,目前还没有,有关这是什么以及为什么复杂的更多信息,请参阅

为n实际推断的类型是D Double。这实际上是两个因素共同作用的结果:恐惧和Haskell的类型默认规则。由于单态限制,n必须被推断为单态类型,因为它在语法上不是函数,也没有显式类型注释。由于这个原因,d1将是不明确的,因为1::forall a。浮动a=>a是多态的。但是,在本例中,Haskell具有数字类型的默认规则,主要是为了避免由于Haskell的多态数字文本而需要解决歧义

由于您已显式地向1添加了类型注释以使其浮动,因此Haskell将其默认规则应用于浮点类型,并将默认规则应用于Double。因此,n的类型被推断为D Double


如果禁用单态限制,那么n的类型将是所有a的更有趣的类型。浮动a=>da,但这是更简单的通用量化类型,而不是您想要的存在量化类型。

Haskell不支持像D这样的类型。浮动a=>a,这是您在这里实际想要的n类型,因为这需要非指示性多态性。虽然1在这里确实是多态的,但由于Haskell的类型默认规则,D1仍然默认为D Double,否则该类型将被认为是不明确的。