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

Mar*_*ler 12 haskell type-inference ghc ghci type-variables

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

Prelude> :t map
map :: (a -> b) -> [a] -> [b]
Run Code Online (Sandbox Code Playgroud)

它似乎从签名中获取类型变量的名称,因为它map定义

map :: (a -> b) -> [a] -> [b]
map _ []     = []
map f (x:xs) = f x : map f xs
Run Code Online (Sandbox Code Playgroud)

在序曲中.这很有道理!我的问题是:当没有给出签名时,如何选择类型变量名?

一个例子是

Prelude> :t map fst
map fst :: [(b, b1)] -> [b]
Run Code Online (Sandbox Code Playgroud)

它选择名称bb1.很明显,重命名必须发生,而只是开始a,b......将给予

map fst :: [(a, b)] -> [a]
Run Code Online (Sandbox Code Playgroud)

相反,我发现它更具可读性.

dfl*_*str 14

据我所知,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
Run Code Online (Sandbox Code Playgroud)

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

castAdd :: (Num a, Num b, Num c) => a -> b -> c
Run Code Online (Sandbox Code Playgroud)

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

编辑:是的,我知道这castAdd是不可能实现的,但它只是一个类型的例子.