Reputation: 153
I am trying to learn Haskell. Currently I am making a function that should take a [String] and 'char' and return in how many strings this char presents.
count [] _ = 0
count (x:xs) v
| elem v x = 1 + count xs
| otherwise = 0 + count xs
How is it done correctly?
!EDIT
I get this error ::
Occurs check: cannot construct the infinite type: a ~ a1 -> a
Relevant bindings include
v :: a1 (bound at prog.hs:7:14)
xs :: [t a1] (bound at prog.hs:7:10)
x :: t a1 (bound at prog.hs:7:8)
count :: [t a1] -> a1 -> a (bound at prog.hs:6:1)
In the second argument of `(+)', namely `count xs'
In the expression: 1 + count xs
Upvotes: 0
Views: 2582
Reputation: 42678
Just for show a folding solution:
count :: String -> Char -> Int
count x c = foldr (\x y -> y+1 if x == c else y) s 0
foldr pick each element and perform the desired operation taking the result as the input for the next item, so in this case, we are initializing it to 0, and adding 1 for each element that is equal to the char passed to te function.
Upvotes: 1
Reputation: 9211
You've got the right idea. elem
is a predicate that answers whether a list contains an element. Given that a String
is a list of char
, it would probably be better to just match on equality. Something like this:
count :: String -> Char -> Int
count "" _ = 0
count (x:xs) v
| x == v = 1 + count xs v
| otherwise = count xs v
Your count
function takes two arguments. In your example code, you're missing the second (the character you're searching for); hence the error.
EDIT The signature is count :: [String] -> Char -> Int
; my mistake. In which case, you should use elem
and it can be simplified to something like:
count :: [String] -> Char -> Int
count [] _ = 0
count (x:xs) v = c + count xs v
where c = if elem v x then 1 else 0
...you always do the count xs v
recursive call, so you don't really need the guard.
Upvotes: 1
Reputation: 6463
count
takes two arguments (a list and a character), but you are invoking it with only one (xs
) in each guard. You should change your function to:
count [] _ = 0
count (x:xs) v
| elem v x = 1 + count xs v
| otherwise = count xs v
Notice that I removed adding zero, because it's redundant and doesn't really make the code more readable.
Upvotes: 1
Reputation: 2855
I would recommend defining the desired signature for count, so you'll get better errors, and a good feeling for the type system (since you're learning haskell)
count :: [String] -> Char -> Int
To make your code work these are in my mind the changes you'd need to make (untested)
count [] _ = 0
count (x:xs) v
| elem v x = 1 + count xs v
| otherwise = count xs v
You could also use built in functions like haskell to make your code a little more readable (less guards and lines), though I think it would make it a little worse performance wise.
Upvotes: 0