使用Haskell将字符串拆分为列表

3
背景: 我一直在阅读Learn You A Haskell和在线教程,但是这个问题困扰了我一个星期,我还是没能解决。

我已经对列表推导和递归有了很大的进展,但是这个问题仍然是我面临的难题。

问题: 我试图将一个字符串(或者我认为是一个字符串)转换成一个分割后的列表。下面是目前我拥有的代码(再次感谢 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 }

3
你遇到了什么错误或问题? - J Fritsch
我刚刚把我的错误添加到了帖子中。 - subtlearray
你在调用 convert 后期望发生什么?看起来你只是试图把结果丢掉:你没有尝试打印它或做任何事情。 - dave4420
我不明白你所说的“分割字符串”是什么意思。 - Luis Casillas
通过“分割字符串”,我的意思是将像这样的内容“在引号中的句子”转换为像这样的内容[“A”,“sentence”,“in”,“a”,“list”]。 - subtlearray
3个回答

6
问题在于`convert'`的结果是一个字符串列表,但您正在尝试将其用作IO操作。您需要对结果进行处理。例如:
print $ convert' contents

您可以将结果打印到屏幕上,例如 print。或者您可以使用 mapM_ putStrLn 将每个元素单独显示在一行上。或者您可以给它一个名称,并继续编写语句,例如:

let converted = convert' contents
...

根据你的评论,看起来你想把这个字符串分成单词列表,例如 convert' "Hello world"["Hello", "world"]。在这种情况下,你根本不需要convert'函数 - 标准的words函数已经做到了!所以你可以直接使用words contents,而不需要定义convert'函数。

我记得Jan告诉我关于单词的事情,但我没有意识到它是一个函数。但我现在应该知道Haskell中的一切都是函数了。 :D 我现在又回到正轨了。谢谢你的帮助。 - subtlearray
2
@SubtleArray,FWIW,Haskell 中并非所有东西都是函数。例如,字符串“this is not a function”是真实的。只有函数才是函数;-) - luqui

5

convert' :: String -> [String],因此convert' contents :: [String]只是一个字符串列表。但您将其放置在了IO块中。

do contents <- readFile whatever
   putStrLn $ ...
   convert' contents

只有类型为IO something的表达式才能出现。将没有IO的表达式转换成IO形式很简单,只需使用return命令:

do contents <- readFile ...
   putStrLn $ ...
   return $ convert' contents

输入正确。但是这个do块的类型是IO [String],所以它与main声明的类型不匹配。如何修复取决于您希望程序执行什么操作。


我明白了。这就像一个 C++ 函数,其功能受其类型限制。谢谢你的澄清。我对 Haskell 还非常陌生,仍在努力理解其语法。 - subtlearray

1

我不明白你在尝试做什么,但最大的问题是你没有正确使用 do 块。 main 的类型为 IO (),这意味着两个限制:

  • 在 do 块中,每个“裸”的语句(没有 <- 的语句)都必须有类型 IO a,其中 a 是某个类型。
  • do 块中的最后一个语句必须具有类型 IO ();你的最后一个语句具有类型 [String](因此你得到的错误)。具有该类型的最简单语句将是 return ()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接