我遇到了一些我刚写的Haskell代码问题。我只是一个初学者,所以我不太了解Haskell的语法,现在这个错误刚刚出现,我不知道如何摆脱它。
无法将预期类型'[Bool]'与实际类型'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"
我想检查fileContent
是否包含单词x
。如果是,我想打印行和行号,其他我想继续搜索,直到我到达文件的末尾。如何迭代fileRows
来检查单词是否在那里?
答案 0 :(得分:2)
这是一种更好的方式来做你想要完成的事情:
我们开始像以前一样在文件中读取,但是fmap在它上面划线,所以我们不需要使用另一个变量。然后我们使用zipWith来运行contains函数。它需要我们要重写的字符串,一行和一个行号。
行号来自[1 ..]部分。这是无限列表的语法糖,从1开始并永远增加1,所以[1,2,3 ..] 因为zipWith需要2个列表,所以它只需要从这个无限列表中获取所需的内容。
它检查该行是否存在,如果是,则创建该字符串,如果不存在则返回Nothing。然后我们调用catMaybes,它接受一个maybes列表,并返回所有正确的值。
现在我们有包含grepped字符串的每一行的输出字符串,所以我们只需要映射列表并打印它。 mapM_就像map一样,除了它采取monadic动作,将它应用于列表中的每个项目,并丢弃结果。
通过拆分这样的函数,我们也可以创建一个很好的纯函数,而不是在没有真正需要时使用一个长IO函数。
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
给定文件foo.txt:
apple
banana
orange
apple banana
orange cherry
cherry apple
输出:
λ> grep "apple"
[1] : apple
[4] : apple banana
[6] : cherry apple
λ> grep "foo"
λ> grep "orange"
[3] : orange
[5] : orange cherry
λ>
答案 1 :(得分:1)
在这一行中,您将函数映射到fileRows,因此您将返回一个Bool数组。
map (isInfixOf x) fileRows == True
您要做的是测试任何行是否包含x。如果您使用any而不是map,它应该可以工作。
any (isInfixOf x) fileRows == True