Reputation: 20435
For this function that counts the number of elements in a list that hold a predicate,
count :: (a -> Bool) -> [a] -> Int
count _ [] = 0
count p (x:xs) = (if (p x) then 1 else 0) + count p xs
how to convert the if-else
expression onto a pattern matching while preserving the summation.
Upvotes: 0
Views: 734
Reputation: 768
You can use bool
function from Data.Bool
module, which does the pattern matching.
bool :: a -> a -> Bool -> a
bool f _ False = f
bool _ t True = t
So,
count :: (a -> Bool) -> [a] -> Int
count _ [] = 0
count p (x:xs) = bool 0 1 (p x) + count p xs
Upvotes: 1
Reputation: 8419
You cannot convert if-else to pattern matching at the level of function definition. Pattern matching is for matching a value against its constructors. If-else
, on the other hand, tests against True
and False
.
By pattern matching, you can decide based on how a value looks like, rather than what the value is. To test what the value is, you use either guards or if-else
expression.
However, you can convert it to pattern matching using a case-of
expression:
count' :: (a -> Bool) -> [a] -> Int
count' _ [] = 0
count p (x:xs) = case (p x) of
True -> 1 + count' p xs
False -> count' p xs
This is pattern matching against the constructor of the Bool
data type, which has two constructors - True
and False
, without any actual data.
Upvotes: 3
Reputation: 22570
You can do:
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
Upvotes: 2