2016-02-19 59 views
2

我已成功地实现(很多尝试之后),一个模拟滤波功能了解Haskell的类型

filter' :: (Num a, Eq a) => (a -> Bool) -> [a] -> [a] 
filter' a [] = [] 
filter' a (x:xs) = if a x 
    then x : filter' a xs 
    else filter' a xs 

我不清楚地了解是类型声明

filter' :: (Num a, Eq a) => (a -> Bool) -> [a] -> [a] 
-- filter' (<10) [1,2,3] 
-- output = [] 

我们传入(<10) [1,2,3] 。但是,在类型声明(a -> Bool)中,我们传递了一个来自列表的递归方式,输出结果是true或false。然而,表达测试(<10)?为什么我们不添加另一个Bool?

+2

添加另一个'Bool'在哪里? – Sibi

+3

(<10)是一个函数并具有类型(a - > Bool)。 [1,2,3]是一个列表并且类型为[a]。过滤器函数使用此函数和一个列表并返回另一个列表。 – yokto

回答

8

您的filter'函数的类型只受到如此限制,因为您已声明它是。如果您不声明该类型,编译器将推断出一个更宽容的类型:(a -> Bool) -> [a] -> [a]。这是相同的类型内置filter功能:

Prelude> :type filter 
filter :: (a -> Bool) -> [a] -> [a] 

表达(< 10)是一个所谓的。这是一个部分应用的功能。

操作<本身就是一个功能:

Prelude> :type (<) 
(<) :: Ord a => a -> a -> Bool 

您可以参阅如下:<是一个函数,有两个参数,无论是通用型a的。类型a必须属于类型Ord。当您用这两个值呼叫<时,返回值为Bool

由于Haskell函数为curried,因此只能使用一些参数调用函数。返回值是一个新的功能“等待其余的参数”:

Prelude> :type (< 10) 
(< 10) :: (Num a, Ord a) => a -> Bool 

此型多一点约束,因为字面10推断属于Num类型类。由于<正在使用中,原始约束(Ord)仍然有效。

表达[1,2,3]是是推断为编译器:

Prelude> :type [1,2,3] 
[1,2,3] :: Num t => [t] 

的值都属于Num类型类。当您使用所有这些类型的在一起,你的所有的推断类型的工会:

Prelude> :type filter (< 10) [1,2,3] 
filter (< 10) [1,2,3] :: (Num a, Ord a) => [a] 

Num类型类是因为使用文字的推断,而Ord类型类是因为使用的的推断<运营商。