2014-10-20 22 views
0

對於這個功能纔是最重要的是保持一個謂詞列表中元素的個數,變換,如果別的模式匹配的遞歸函數

count :: (a -> Bool) -> [a] -> Int 
count _ [] = 0 
count p (x:xs) = (if (p x) then 1 else 0) + count p xs 

如何將if-else表達式轉換到模式匹配,同時保留總和。

+0

這是一個有點不清楚你問什麼,但您尋找的'數 'P(X:XS)真= 1 +算' P XS(PX ); count'p(x:xs)False = count'p xs(p x)'? – Zeta 2014-10-20 11:55:00

+1

我不認爲在這裏切換到守衛/模式匹配是很聰明的。我會寫你的函數爲'count p = length'。過濾器p'完成。或者'count p = foldr(\ x - > if p x then(+1)else id)0':有時候if'一點都不壞,這當然比模式匹配好。 – leftaroundabout 2014-10-20 12:00:48

+0

@leftaroundabout同意,也注意到這個理解'count'p xs = length [x | x < - xs,p x]',但想知道這個特定的轉換... – elm 2014-10-20 12:02:24

回答

2

你可以這樣做:

count' :: (a -> Bool) -> [a] -> Int 
count' _ [] = 0 
count' p (x:xs) | p x = 1 + count' p xs 
count' p (x:xs) | otherwise = 0 + count' p xs 
+1

我會改變'count'p(x:xs)|否則'只是'| otherwise'。 – chi 2014-10-20 12:08:51

3

您不能轉換的if-else圖案在函數定義的水平相匹配。模式匹配用於將值與其構造函數進行匹配。另一方面,If-else針對TrueFalse進行測試。

通過模式匹配,您可以決定基於值如何的樣子,而不是值是什麼。要測試其值是什麼,請使用警衛或if-else表達式。

但是,可以使用case-of表達其轉換爲模式匹配:

count' :: (a -> Bool) -> [a] -> Int 
count' _ [] = 0 
count p (x:xs) = case (p x) of 
        True -> 1 + count' p xs 
        False -> count' p xs 

這是圖案針對Bool數據類型的構造,其具有兩個構造匹配 - TrueFalse,沒有任何實際數據。

1

您可以使用Data.Bool模塊中的bool函數進行模式匹配。

bool :: a -> a -> Bool -> a 
bool f _ False = f 
bool _ t True = t 

所以,

count :: (a -> Bool) -> [a] -> Int 
count _ [] = 0 
count p (x:xs) = bool 0 1 (p x) + count p xs