0

I want to create a function in haskell, that returns the number of times a single word is a prefix of a list of words. For example: for the word "go" and the list of words ["ace","going", "gone", "golf"], it should return 3. What I have so far is this:

numberOfPrefixes _ [] = error ("Empty list of strings")

numberOfPrefixes [] _ = error ("No word")

numberOfPrefixes (x:xs) (y:ys)

                       | isPrefixOf (x:xs) y = 1 + numberOfPrefixes(x:xs) ys

                       | otherwise = 0

But this only works if the first element of the list of words is actually a prefix. If the first element is not a prefix, the whole thing falls apart. Any help making this right?

isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
isPrefixOf [] _ = True
isPrefixOf _ [] = False
isPrefixOf (x:xs) (y:ys) = x == y  && isPrefixOf xs ys
5
  • Hi, I know you're new to SO, but if you have a question on my answer, post as it as a comment on my answer so that I see it :) Second, fix you're indentation and change y:ys to just y in the check and it works fine Commented Oct 14, 2013 at 14:26
  • So i've got another question now. Any help ? And thank you for your advice, it was very helpful Commented Oct 14, 2013 at 15:09
  • Post this as a seperate question and I'd be happy to. Commented Oct 14, 2013 at 15:16
  • Please don't completely change your question after receiving an answer. It's very frustrating for the people who took the time to answer and who ever finds the question in the future gains no benefit from it since the answers are now without a question. Commented Oct 14, 2013 at 15:19
  • Sorry i understand, i posted the new question here: stackoverflow.com/questions/19363151/… Commented Oct 14, 2013 at 15:22

1 Answer 1

3

Here's how I'd write this

 (.:) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
 (.:) = (.) . (.) -- A common utility definition
 infixr 9 .:

 prefixCount :: Eq a => [a] -> [[a]] -> Integer
 prefixCount = length .: filter . isPrefixOf

Or writing it pointfully

 prefixCount l ls = length $ filter (isPrefixOf l) ls

If you really want to write it recursively

 prefixCount l [] = 0
 prefixCount x (l:ls) | <is prefix?> = 1 + prefixCount x ls
                      | otherwise    = prefixCount x ls

and just fill in <is prefix?> with a check whether x is a prefix is of l

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

6 Comments

Can you explain the recursive solution? Because i'm having a hard time trying to understand it. Is it possible to make a little more simple ?
@user2878641 An empty list has 0 elements with the right prefix. Otherwise, get the first element, add 1 to the rest of the count of the rest of the list. Otherwise, add 0 to the count of the rest of the list
i want to use this function that i created earlier to write this one: isPrefixOf :: (Eq a) => [a] -> [a] -> Bool isPrefixOf [] _ = True isPrefixOf _ [] = False isPrefixOF (x:xs) (y:ys) = x == y && isPrefixOf xs ys
@user2878641 Ok, that works fine. This is the same as yours, just cleaned up. And instead of returning 0 when it's not a prefix, it returns the count of the rest of the list
Try writing this out long hand for your example.
|

Your Answer

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