Reputation: 19
I am having an issue with some Haskell code I just wrote. I am just a beginner so I don't know much about the syntax of Haskell and now this error just popped up and I have no clue how to get rid of it.
Couldn't match expected type ‘[Bool]’ with actual type ‘Bool’
grep :: String -> IO()
grep x = do
fileContent <- readFile "/home/User/Desktop/foo.txt"
let fileRows = lines fileContent
let rowNumbers = -1
if (map (isInfixOf x) fileRows == True)
then do let rowNumbers2 = rowNumbers
let rowNumbers = rowNumbers2+1
putStrLn ("[" ++ show(rowNumbers) ++ "] : " ++ x)
else do let rowNumbers2 = rowNumbers
let rowNumbers = rowNumbers2+1
print "False"
I want to check if fileContent
contains the word x
. If yes, I want to print the line and the line number, otheriwse I want to keep searching until I reach the end of the file. How can I iterate through fileRows
to check if the word is in there?
Upvotes: 0
Views: 340
Reputation: 1359
Here's a more haskelly way to do what you're trying to accomplish:
We start by reading in the file as before, but fmap lines over it so we don't need to use another variable. Then we use zipWith to run the contains function. It takes the string we're grepping for, a line, and a line number.
The line number is from the [1..] section. This is syntactic sugar for an infinite list, starting at 1 and increasing by 1 forever, so [1,2,3..] Because zipWith takes 2 lists, it only takes as much as it needs from this infinite list.
It checks if the line is present, and if it is, creates the string, and if not returns Nothing. Then we call catMaybes, which takes a list of maybes, and returns all the just values.
Now we have the output string for every line that contains the grepped string, so we just need to map over the list and print it. mapM_ is like map, except it takes a monadic action, applies it to each item in the list, and discards the results.
By splitting up the functions like this, we also get to make a nice pure function instead of having one long IO function when it's not really needed.
import Data.List (isInfixOf)
import Data.Maybe (catMaybes)
grep x = do
fileContent <- lines <$> readFile "foo.txt"
let result = catMaybes $ zipWith (contains x) fileContent [1..]
mapM_ putStrLn result
contains x y lineNum
| x `isInfixOf` y = Just $ "[" ++ show lineNum ++ "] : " ++ y
| otherwise = Nothing
Given a file foo.txt:
apple
banana
orange
apple banana
orange cherry
cherry apple
It outputs:
λ> grep "apple"
[1] : apple
[4] : apple banana
[6] : cherry apple
λ> grep "foo"
λ> grep "orange"
[3] : orange
[5] : orange cherry
λ>
Upvotes: 2
Reputation: 9954
In this line, you are mapping a function over fileRows, so you're returning an array of Bool.
map (isInfixOf x) fileRows == True
What you want to do is test if any row contains x. If you use any instead of map, it should work.
any (isInfixOf x) fileRows == True
Upvotes: 1