问题
I want to manually derive the type of:
f1 x xs = (filter . (<)) x xs
First time we see x
, so:
x :: t1
Then (<)
has this type:
(<) :: Ord a1 => a1 -> a1 -> Bool
We can only say (< x)
if the following types can be unified:
t1 ~ a1
Then
x :: a1
So
(<x) :: Ord a1 => a1 -> Bool
Filter has this type
filter :: (a2 -> Bool) -> [a2] -> [a2]
First time to see xs, so:
xs :: t2
We can only say (filter . (<)) x xs
if the following types can be unified:
a1 -> Bool ~ a2 -> Bool
t2 ~ [a2]
So I get that f1 :: (a2 -> Bool) -> [a2] -> [a2]
, the same type as filter
, when the correct type is Ord a => a -> [a] -> [a]
(asking GHCi).
Any help?
回答1:
The constraint
a1 -> Bool ~ a2 -> Bool
can be broken down to
a1 ~ a2
and the obviously true
Bool ~ Bool
So you have a1 ~ a2
. You already know that x
is a1
, xs
is [a2]
and, thanks to filter
, the result type is [a2]
. Therefore, you end up with:
f1 :: Ord a2 => a2 -> [a2] -> [a2]
(Don't forget the class constraint a1
got from (<)
.)
回答2:
We can process given expressions in a top-down manner. This way there's no need to guess what goes where, the derivation happens purely mechanically, with minimal room for error:
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]
Another way to tackle this is to notice that eta reduction can be performed there in the definition of 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]
Of course we use the right associativity of arrows in types: a -> b -> c
is actually a -> (b -> c)
.
We also use a general scheme for type derivations
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
来源:https://stackoverflow.com/questions/23327370/manual-derivation-of-the-type-for-f1-x-xs-filter-x-xs