正如 dave4420 提到的,
(.) :: (b -> c) -> (a -> b) -> a -> c
那么是什么类型的(.) (.)
呢?dave4420 跳过那部分,所以它是:(.)
接受一个类型的值b -> c
作为它的第一个参数,所以
(.) :: ( b -> c ) -> (a -> b) -> a -> c
(.) :: (d -> e) -> ((f -> d) -> f -> e)
所以我们有b ~ d->e
and c ~ (f -> d) -> f -> e
,结果类型(.)(.)
是(a -> b) -> a -> c
。代入,我们得到
(a -> d -> e) -> a -> (f -> d) -> f -> e
重命名,我们得到(a -> b -> c) -> a -> (d -> b) -> d -> c
. 这是一个f
需要二元函数g
、一个值x
、一个一元函数h
和另一个值的函数y
:
f g x h y = g x (h y)
这是可以实现这种类型的唯一方法:g x :: b -> c
,h y :: b
和 so g x (h y) :: c
,根据需要。
当然,在 Haskell 中,“一元”函数需要一个或多个参数。类似地,“二进制”函数需要两个或多个参数。但不少于两个(所以使用 egsucc
是不可能的)。
我们也可以通过编写方程式,组合符式1来解决这个问题。等式推理很容易:
(.) (.) x y z w q =
((.) . x) y z w q =
(.) (x y) z w q =
(x y . z) w q =
x y (z w) q
我们只是根据需要将尽可能多的变量放入混合中,然后来回应用定义。q
这是一个额外的,所以我们可以把它扔掉并得到最终的定义,
_BB x y z w = x y (z w)
(巧合的是,(.)
被称为B -combinator)。
1 a b c = (\x -> ... body ...)
等价于a b c x = ... body ...
,反之亦然,前提是x
不出现在 之间{a,b,c}
。