模式匹配推断类型

时间:2017-01-02 18:53:36

标签: haskell pattern-matching higher-rank-types

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

1 个答案:

答案 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,但这是更简单的通用量化类型,而不是您想要的存在量化类型。