我想手动派生类型:
f1 x xs = (filter . (<)) x xs
我们第一次看到x
,所以:
x :: t1
然后(<)
有这种类型:
(<) :: Ord a1 => a1 -> a1 -> Bool
如果可以统一以下类型,我们只能说(< x)
:
t1 ~ a1
然后
x :: a1
所以
(<x) :: Ord a1 => a1 -> Bool
过滤器具有此类型
filter :: (a2 -> Bool) -> [a2] -> [a2]
第一次看到xs,所以:
xs :: t2
如果可以统一以下类型,我们只能说(filter . (<)) x xs
:
a1 -> Bool ~ a2 -> Bool
t2 ~ [a2]
当正确的类型为f1 :: (a2 -> Bool) -> [a2] -> [a2]
(询问GHCi)时,我得到filter
,类型与Ord a => a -> [a] -> [a]
相同。
任何帮助?
答案 0 :(得分:3)
我们可以自上而下的方式处理给定的表达式。这样就没有必要猜测究竟是什么,推导纯粹是机械地发生的,只有极小的错误空间:
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]
解决这个问题的另一种方法是注意在f1
的定义中可以执行 eta reduction :
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)
。
我们还使用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