2014-10-20 54 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