1

I'm trying to write a program that reads a text file, then displays the frequencies and count of words in the file. What I need to do next is filter certain words from the text file. I have been looking at online resources for a couple of hours and still can't find what I'm looking for!

I have provided my code for the program so far below:

lowercase = map toLower
top doc = wordPairs
    where
        listOfWords = words (lowercase doc)
        wordGroups  = group (sort listOfWords)
        wordPairs   = reverse
                    $ sort
                    $ map (\x -> (length x, head x))
                    $ filterWords
                    wordGroups

filterWords :: String -> String
filterWords = filter (all (`elem` ["poultry outwits ants"])) . words
8
  • 1
    Are you trying to filter out the words "poultry", "outwits", "ants"? The function ``` elem ["poultry outwits ants"]``` will only filter out a string matching the exact value "poultry outwits ants", not any of the strings "poultry", "outwits", or "ants". Commented May 8, 2015 at 16:20
  • 2
    Also, don't use tabs in Haskell. It's possible to do, but you're a lot more likely to run into weird syntax errors. Just use spaces, they always work. Commented May 8, 2015 at 16:21
  • @bheklilr Yes, that is exactly what I am trying to do. I have changed the filter code to 'filterWords :: String -> [String] filterWords = filter (elem ["poultry", "outwits", "ants"] . words' but it still gives me the same error "parse error (possibly incorrect indentation or mismatched brackets)" I'm not sure how to go about solving this issue. Thanks Commented May 8, 2015 at 16:28
  • 1
    change your tabs to spaces first, does that help? You'll just have type errors after that (I think) Commented May 8, 2015 at 16:31
  • 1
    indentation. You had tab characters in your code that you had initially posted. You should be able to configure your editor to insert some number of spaces (I like 4) whenever you press the tab key on your keyboard. If you can't make your editor do that, stop using notepad.exe and get a real editor :P Commented May 8, 2015 at 16:34

2 Answers 2

1

It might be easier if you split the program in a different way. For example

import Data.List(group,sort)
import Control.Arrow((&&&))

freq :: Ord a => [a] -> [(Int,a)]
freq = reverse . sort . map (length &&& head) . group . sort

second part will be defining the input to this function. You want to filter only certain elements.

select :: Eq a => [a] -> [a] -> [a]
select list = filter (`elem` list)

these will make testing easier since you don't need the specific typed input.

Finally, you can tie it all together

freq $ select ["a","b","c"] $ words "a b a d e a b b b c d e c"

will give you

[(4,"b"),(3,"a"),(2,"c")]
Sign up to request clarification or add additional context in comments.

Comments

1

There is my code which solve your problem

top :: String -> [(Int,String)] --Signature is always important
top = sorter . wordFrequency . groups . filtered --just compose `where` functions
    where
        -- This will filter your words
        filtered = filter (`notElem` ["poultry","outwits","ants"]) . words . map toLower 
        -- Group your words
        groups = group . sort 
        -- Create the pairs of (count, word)
        wordFrequency = map (length &&& head)
        -- Sort your list by first. for reverse just switch a and b
        sorter = sortBy (\ a b -> fst b `compare` fst a)

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.