Syngularity
Syngularity

Reputation: 824

Count a occurrence of a specific word in a sentence haskell

I'm new in Haskell and I'm tring to write a simple function that counts the number of occurences of a substring in a string.

For example : "There is an apple" and I want to count how many times "is" in the sentence, in this case the result should be 1.

This is what I've tried:

countOf :: String -> Int
countOf x = length [n | n <- words x, filter "is" x]

According what I've studied it should work, but it doesn't. I really don't know how to solve the problem, and also don't know what the error message I get means:

input:1:41:
     Couldn't match expected type `Bool' with actual type `[a0]'
     In the return type of a call of `filter'
     In the expression: filter "a" x
     In a stmt of a list comprehension: filter "a" x

Upvotes: 2

Views: 1637

Answers (5)

dganti
dganti

Reputation: 305

One could also try a foldr:

countOf :: String -> Int
countOf x = foldr count 0 (words x) 
  where 
  count x acc = if x == "is" then acc + 1 else acc

Upvotes: 0

vek
vek

Reputation: 1543

Actually, you try to count the number of occurences of a word in a string. In case you look for a substring:

import Data.List (inits, tails)

countOf = length . filter (=="is") . conSubsequences
  where
    conSubsequences = concatMap inits . tails

Upvotes: 0

Lee
Lee

Reputation: 144206

You can put the comparison straight in the comprehension:

countOf x = length [n | n <- words x, n == "is"]

Upvotes: 0

bheklilr
bheklilr

Reputation: 54078

The function filter has the type

filter :: (a -> Bool) -> [a] -> [a]

This means that its first argument is another function, which takes an element and returns a Bool, and it applies this function to each element of the second argument. You're giving a String as the first argument instead of a function. Maybe you want something more like

countOf x = length [n | n <- words x, filter (\w -> w == "is") x]

But this won't work either! This is because any extra expression in a list comprehension has to be a Bool, not a list. filter returns a list of elements, not a Bool, and this is actually the source of your compiler error, it expects a Bool but it sees a list of type [a0] (it hasn't even gotten far enough to realize it should be [String]).

Instead, you could do

countOf x = length [n | n <- words x, n == "is"]

And this would be equivalent to

countOf x = length (filter (\w -> w == "is") (words x))

Or with $:

countOf x = length $ filter (\w -> w == "is") $ words x

Haskell will actually let us simplify this even further to

countOf x = length $ filter (== "is") $ words x

Which uses what is known as an operator section. You can then make it completely point free as

countOf = length . filter (== "is") . words

Upvotes: 8

Sibi
Sibi

Reputation: 48766

I would do like this:

countOf :: String -> Int
countOf x = length [n | n <- words x, compare "is" n == EQ] 

Demo in ghci:

ghci> countOf "There is an apple"
1

Upvotes: 0

Related Questions