我想手动导出以下类型:
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]。
有什么帮助吗?
发布于 2014-04-27 18:52:22
约束
a1 -> Bool ~ a2 -> Bool可以分解成
a1 ~ a2显然是真的
Bool ~ Bool所以你有a1 ~ a2了。您已经知道x是a1,xs是[a2],由于filter,结果类型是[a2]。因此,您的结果是:
f1 :: Ord a2 => a2 -> [a2] -> [a2](不要忘记a1从(<)获得的类约束。)
发布于 2014-04-27 21:29:02
我们可以用自顶向下的方式处理给定的表达式。这样就不需要猜测哪里去了,推导完全是机械的,只有最小的出错空间:
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减少操作。
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 :: ahttps://stackoverflow.com/questions/23327370
复制相似问题