手动推导`f1 x xs =(filter。(<))x xs`的类型

时间:2014-04-27 18:37:30

标签: haskell types ghci unification

我想手动派生类型:

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]相同。

任何帮助?

1 个答案:

答案 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