GHC 如何推断此 GADT 的预期类型?

How does GHC infer the intended type for this GADT?

我对 GHC 类型推断的理解是,在没有类型注释的情况下,它将默认为 Hindley-Milner。然而,令我惊喜的是,GHC 为 f 推断出 Num p => G a -> p 而不是 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 推断出正确的类型?

这是一个更极端的例子:

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