让我们看看我们知道什么。让我们看看
comp2
s独立实现:
comp2 = comp comp comp
让我们考虑一下
comp
s类型签名:
comp :: (b -> c) -> (a -> b) -> (a -> c)
现在,结果是
将是
comp公司
应用于两个参数,即
comp公司
类型签名。因此,我们知道
组件2
类型为
a -> c
,我们只是不知道
a
和
c
还没有。
统一
替换
已知类型变量及其具体类型。这两个参数都是
comp公司
,但它们应该有不同的类型:
b -> c
和
a -> b
分别地让我们添加一些类型注释,使其更加清晰:
comp2 = (comp (comp :: b -> c)
(comp :: a -> b))
我们可以首先尝试统一
b->c
类型为
comp公司
确定什么
b
和
c
是,但我们需要进行一些alpha重命名,以便变量名不会冲突:
b -> c
(b1 -> c1) -> (a1 -> b1) -> (a1 -> c1)
b = b1 -> c1
c = (a1 -> b1) -> (a1 -> c1)
a->b
:
a -> b
(b2 -> c2) -> (a2 -> b2) -> (a2 -> c2)
a = b2 -> c2
b = (a2 -> b2) -> (a2 -> c2)
但是等等!对于同一类型变量,我们现在有两个不同的定义,
b
,所以这些也必须统一。让我们对这两种类型执行相同的过程:
b1 -> c1
(a2 -> b2) -> (a2 -> c2)
b1 = a2 -> b2
c1 = a2 -> c2
现在,回到我们原来的类型
组件2
,我们可以执行一系列替换,最终得到一个完整的类型:
a -> c | type of comp2, from the return type of comp
(b2 -> c2) -> c | substituting the definition of a
(b2 -> c2) -> (a1 -> b1) -> (a1 -> c1) | substituting the definition of c
(b2 -> c2) -> (a1 -> (a2 -> b2)) -> (a1 -> c1) | substituting the definition of b1
(b2 -> c2) -> (a1 -> (a2 -> b2)) -> (a1 -> (a2 -> c2)) | substituting the definition of c1
(b2 -> c2) -> (a1 -> a2 -> b2) -> a1 -> a2 -> c2 | removing unnecessary parentheses
(c -> d) -> (a -> b -> c) -> a -> b -> d | alpha renaming
您会注意到这与手动指定的类型相同。