正如 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 和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 和g x (h y) :: c,根据需要。
当然,在 Haskell 中,“一元”函数需要一个 或多个 参数;类似地,“二进制”函数需要两个 或更多 参数。但不少于两个(因此使用例如succ 是不可能的)。
我们也可以通过编写方程式来解决这个问题,combinators-style1。 Equational reasoning is easy:
(.) (.) 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)。
1a b c = (\x -> ... body ...)等价于a b c x = ... body ...,反之亦然,前提是x不出现在{a,b,c}中。