我们可以以自上而下的方式处理给定的表达式。这样就不需要猜测去哪里了,推导纯粹是机械地发生的,错误的空间最小:
f1 x xs = (filter . (<)) x xs
f1 x xs :: c (filter . (<)) x xs :: c
f1 x :: b -> c xs :: b
f1 :: a -> b -> c x :: a
(filter . (<)) x xs :: c
filter ((<) x) :: b -> c c ~ [d] , b ~ [d]
filter :: (d->Bool) -> [d] -> [d] (<) x :: d -> Bool
(<) :: (Ord a) => a -> a -> Bool
(<) x :: d -> Bool a ~ d , (Ord a)
f1 :: (Ord a) => a -> [a] -> [a]
解决这个问题的另一种方法是注意可以在 的定义中执行eta 减少f1:
f1 x xs = (filter . (<)) x xs
f1 = (.) filter (<)
(.) :: ( b -> c ) -> ( a -> b ) -> (a->c)
(.) filter (<) :: t1
(.) :: ((d->Bool) -> ([d]->[d])) -> ((Ord a) => a -> (a->Bool)) -> t1
b ~ d -> Bool , c ~ [d] -> [d] , t1 ~ a -> c , (Ord a)
b ~ a -> Bool
-------------
d ~ a
f1 :: t1 ~ (Ord a) => a -> c
~ (Ord a) => a -> [d] -> [d]
~ (Ord a) => a -> [a] -> [a]
当然,我们在类型中使用箭头的右关联性:a -> b -> c实际上是a -> (b -> c)。
我们还使用类型推导的通用方案
f x y z :: d
f x y :: c -> d , z :: c
f x :: b -> c -> d , y :: b
f :: a -> b -> c -> d , x :: a