返回故事:上周我一直在努力解决这个问题,在线阅读Learn You A Haskell和教程,但我无法理解。
我在理解列表理解和递归方面取得了很大的进步,但是这个问题仍然是我的一个方面。
问题:我正在尝试将String(或我认为是String)转换为分割列表。这是我到目前为止的代码(再次感谢Jan的帮助)。它导入.txt文件的内容。
import System.Environment
main :: IO ()
main = do
args <- getArgs
if null args
then putStrLn "usage: ./pattern dataset.txt"
else do contents <- readFile $ head args
putStrLn $ "Filer1: " ++ filterLower(contents)
convert' contents
filterLower :: String -> String
filterLower st = [ c | c <- st, c `elem` ['A'..'Z']]
我尝试制作自己的转换功能:
convert' :: String -> [String]
convert' x = (x:[])
它有效,但它不能解决这个问题。
任何帮助都将不胜感激。
错误:这是我经常收到的错误。
Couldn't match expected type `IO ()' with actual type `[String]'
In the return type of a call of `convert''
In the expression: convert' contents
In the expression:
do { contents <- readFile $ head args;
putStrLn $ "-: " ++ filterLower contents;
convert' contents }
答案 0 :(得分:6)
问题是convert'
的结果是字符串列表,但您尝试将其用作IO操作。你必须对结果做点什么。例如,
print $ convert' contents
会将结果打印到屏幕上。或者你可以使用,例如mapM_ putStrLn
将每个元素打印出来。或者您可以给它起一个名字,然后继续编写语句,例如:
let converted = convert' contents
...
根据您的评论,似乎您尝试分割字符串的方式是将其转换为单词列表,例如convert' "Hello world"
≡["Hello", "world"]
。在这种情况下,您根本不需要convert'
- 标准words
功能就是这样!因此,您可以使用words contents
而不是定义convert'
。
答案 1 :(得分:5)
convert' :: String -> [String]
,所以convert' contents :: [String]
只是一个字符串列表。但是你把它放在一个IO块中,
do contents <- readFile whatever
putStrLn $ ...
convert' contents
只能出现IO something
类型的表达式。有一种简单的方法可以将IO-less表达式转换为IO,只需return
它:
do contents <- readFile ...
putStrLn $ ...
return $ convert' contents
输入正确。但是这个do-block的类型为IO [String]
,因此它与声明的main
类型不匹配。如何解决这个问题取决于你希望程序做什么。
答案 2 :(得分:1)
我不明白你在这里要做什么,但最大的问题是你没有正确使用do
- 阻止。 main
的类型为IO ()
,这意味着两个约束:
<-
的语句)对于某些IO a
必须具有a
类型。do
- 块中的最终语句必须包含IO ()
类型;你的最终陈述的类型为[String]
(因此你得到的错误)。具有该类型的最简单的语句是return ()
。