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

4
我写了这个函数:
compose []     = id
compose (x:xs) = x  . (compose xs)

当我询问类型时:

:t compose
compose :: [b -> b] -> b -> b

为什么输出结果是 compose :: [b -> b] -> b -> b 而不是 compose :: [a -> a] -> a -> a,即使在字母表中 a 比 b 先?请注意以下另一个示例:
badImplementationOfCompose []     = id
badImplementationOfCompose (x:xs) =  (badImplementationOfCompose xs)

:t badImplementationOfCompose
badImplementationOfCompose :: [a1] -> a2 -> a2

它可能会给出一些提示...


GHCi试图使用您使用的函数类型中出现的类型变量名称。由于推理算法相当复杂,因此很难猜测哪个名称会生效。在这里,似乎b来自于.的类型,或者至少这是我的猜测。明显执行的顺序统一选择了它,而不是其他的名称。 - chi
从这两个目标中,较旧的那个以整洁的方式解释了其要点,而较新的那个则讨论了一些边缘情况。 - duplode
@duplode 感谢您一如既往的帮助。 - developer_hatch
2个回答

3
我猜这与“.”的类型有关。
(.) :: (b -> c) -> (a -> b) -> a -> c

当推断类型时,它会从那里开始替换。

a 必须等于 bb 必须等于 c。简而言之,我猜测它尝试使类型变量命名与在使用的子函数中使用的类型变量名称保持一致(如果可能的话)。


0

我的猜测:

如果没有给出任何函数,GHCi会从一个通用类型开始,我在谈论我的第二个例子:

badImplementationOfCompose []     = id
badImplementationOfCompose (x:xs) =  (badImplementationOfCompose xs)

它的类型是id,即a -> a,因此如果需要另一个类型变量,则从一开始逐个添加。

badImplementationOfCompose :: [a1] -> a2 -> a2

我想,也许@chi是绝对正确的,这些名称来自函数,所以我用自己的id做了一个案例:

id2 :: c -> c
id2 x = x

badImplementationOfCompose []     = id2
badImplementationOfCompose (x:xs) =  (badImplementationOfCompose xs)

并且类型与预期相符:

:t badImplementationOfCompose
badImplementationOfCompose :: [a] -> c -> c

第一个类型变量是由GHCi创建的a,而c -> c则来自于id2


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接