我对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的正确类型?
答案 0 :(得分:2)
这是一个更极端的例子:
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