GHC如何推断出这个GADT的预期类型?

时间:2018-06-17 09:23:41

标签: haskell types ghc type-inference gadt

我对GHC类型推断的理解是,在没有类型注释的情况下,它将默认为Hindley-Milner。但令我惊喜的是,GHC推断Num p => G a -> p f而不是Num p => G Char -> p

data G a where
  A :: a      -> G a
  B :: String -> G Char

f (A a) = 42
f (B s) = 24

我的问题是它是如何做到的,在其他情况下它会推断出GADT的正确类型?

1 个答案:

答案 0 :(得分:2)

GHC “disables” Hindley-Milner in GADT pattern matching, so as to prevent dynamic type information from escaping its scope.

这是一个更极端的例子:

import Data.Void

data Idiotic :: * -> * where
  Impossible :: !Void -> Idiotic Void
  Possible :: a -> Idiotic a

不存在Void类型的任何值,因此不可能使用Impossible构造函数。因此,Idiotic a实际上与Identity a同构,IOW与a本身同构。因此,任何采用Idiotic值的函数都只通过Possible模式匹配来完整描述。基本上,它总是归结为

sobre :: Idiotic a -> a
sobre (Possible a) = a

在实践中很容易使用。

但就类型系统而言,其他构造函数也匹配,实际上需要禁用incomplete pattern警告:

sobre (Impossible a) = {- Here, a::Void -} a

但是如果编译器向外传播这种类型的信息,你的函数最终会得到完全没用的签名

sobre :: Idiotic Void -> Void