GHCi如何选择类型变量的名称?

时间:2011-12-15 12:13:05

标签: haskell type-inference ghc ghci type-variables

使用交互式GHC解释器时,可以询问表达式的推断类型:

Prelude> :t map
map :: (a -> b) -> [a] -> [b]

似乎它从签名中获取了类型变量的名称,因为mapdefined

map :: (a -> b) -> [a] -> [b]
map _ []     = []
map f (x:xs) = f x : map f xs
前言中的

。这很有道理!我的问题是:如果没有给出签名,如何选择类型变量名称?

一个例子是

Prelude> :t map fst
map fst :: [(b, b1)] -> [b]

选择了名称bb1。显然必须重命名,但只需从a开始,b,......就会给出

map fst :: [(a, b)] -> [a]
相反,我发现它更具可读性。

1 个答案:

答案 0 :(得分:13)

据我了解,ghci按照推断类型的顺序选择名称。它使用您提到的命名方案来确定结果的类型名称,即[b],因为这是map定义中指定的类型名称。然后它决定作为map的第一个参数的函数也应该返回b类型的函数。

因此,要命名的剩余类型变量是fst的参数元组中第二个元素的类型变量,并再次查看fst的定义以决定使用哪个名称。 fst :: (a, b) -> a的定义,因此b将是此处的首选名称,但由于b已被采用,因此会附加1以使其成为b1

我认为这个系统在你不处理任意类型的情况下具有优势,就像这里的情况一样。如果结果类型看起来像这样,例如:

castAdd :: (Num n, Num n1, Num n2) => n -> n1 -> n2

......它可以说比以下更具可读性:

castAdd :: (Num a, Num b, Num c) => a -> b -> c

...因为您n#主要依赖于Num表示数字类型,因为class Num n where ...的类定义为castAdd

编辑:是的,我知道{{1}}无法实现,但它只是一个类型示例。