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

时间:2012-01-12 17:38:14

标签: string list haskell io

返回故事:上周我一直在努力解决这个问题,在线阅读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 }

3 个答案:

答案 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 (),这意味着两个约束:

  • do-block中的每个“bare”语句(没有<-的语句)对于某些IO a必须具有a类型。
  • do - 块中的最终语句必须包含IO ()类型;你的最终陈述的类型为[String](因此你得到的错误)。具有该类型的最简单的语句是return ()