如何通过IO操作运行列表

时间:2017-07-19 15:13:48

标签: haskell types io list-comprehension monads

所以我正在编写一个程序来检查.txt文件的每一行是否是回文,

import System.IO

main :: IO()
main = do {
content <- readFile "palindrom.txt";
print content;
print (lines content);
singleWord (head (lines content));
return ();
}

palindrom :: [Char] -> Bool
palindrom a = a == reverse a

singleWord :: [Char] -> IO()
singleWord a = do { 
print (length a);
print (show (palindrom a));
}

但我需要在整个列表中运行singleWord (head (lines content))而不是singleWord

问题在于map或正常列表理解我总是得到大量不同的错误,与lines content(应该是一个字符串或IO字符串数组)有关,显然总是类型我不想要(我已经尝试过永久性地处理类型声明,但它仍然是错误的类型,或者是正确的类型,但是在一个额外的数组层或其他什么)。

我的最后一次尝试是通过递归来遍历数组,只需要一些额外的代码:

walkthrough [] = []
walkthrough x = do { singleWord head x; walkthrough (tail x) }

无论如何我无法正确地进行类型转换。

它应该替换singleWord (head (lines content))中的main,如果我尝试使用类型分类,例如

walkthrough :: [[Char]] -> [[Char]]
walkthrough [] = ["Hi"]
walkthrough x = do { singleWord head x; walkthrough (tail x) }

我得到了

Couldn't match type `IO' with `[]'
      Expected type: [()]
        Actual type: IO ()

或其他一些不合适的东西。

3 个答案:

答案 0 :(得分:4)

您正在寻找名为mapM_的函数。

main :: IO ()
main = do {
  content <- readFile "palindrom.txt";
  mapM_ singleWord (lines content);
};


palindrome :: [Char] -> Bool
palindrome a = (a == reverse a)

singleWord :: [Char] -> IO()
singleWord a = do {
  let {
    adverb = (if palindrome a then " " else " not ");
  };
  putStrLn  (a ++ " is" ++ adverb ++ "a palindrome.");
};

答案 1 :(得分:3)

应该

walkthrough [] = return ()                    -- this is the final action
walkthrough x  = do { singleWord (head x)     -- here you missed the parens 
                    ; walkthrough (tail x) }

或更好,

walkthrough []     = return () 
walkthrough (x:xs) = do { singleWord x        -- can't make that mistake now!
                        ; walkthrough xs}

并在主walkthrough (lines content)区块中将其称为do

正如其他人所指出的那样,walkthroughmapM_ singleWord相同。

你也可以用列表理解来编写它,

walkthrough xs = sequence_ [ singleWord x | x <- xs]

sequence_ :: Monad m => [m a] -> m ()将操作列表转换为一系列操作,放弃其结果并最终生成()sequence_ = foldr (>>) (return ())sequence_ (map f xs) === mapM_ f xs,所以最终都会绑定。

答案 2 :(得分:2)

使用mapM_ singleWord (lines content)。为简单起见,请将mapM_视为。

mapM_ :: (a -> IO ()) -> [a] -> IO ()