Reputation: 824
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
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
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
Reputation: 144206
You can put the comparison straight in the comprehension:
countOf x = length [n | n <- words x, n == "is"]
Upvotes: 0
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
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