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
我对 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