2016-02-19 78 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類型類是因爲使用的的推斷<運營商。