0

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
3
  • So you're trying the total number of occurrences of the character in all strings? Or the amount of strings in which the character occurs at least once? Commented Dec 23, 2015 at 12:09
  • Amount of strings in which the character occurs at least once Commented Dec 23, 2015 at 12:10
  • Alright give me a sec Commented Dec 23, 2015 at 12:11

4 Answers 4

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

4 Comments

The function takes a list of Strings, not a single String.
@Kapol I didn't spot that! In which case, ignore what I said about elem: that's what should be used!
Yep .. just noticed it myself :D
Fixed and added a simplification
1

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.