【问题标题】:How do I run through a list with an IO operation如何使用 IO 操作遍历列表
【发布时间】:2017-07-19 15:13:47
【问题描述】:

所以我正在编写一个程序来检查 .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 而不是 singleWord (head (lines content))

问题在于,对于map 或普通的列表理解,我总是会遇到大量与lines content(应该是字符串或IO 字符串数组)有关的各种错误,显然总是我不知道的类型。不想要(我已经尝试过永远搞乱类型声明,但它一直是错误的类型,或者是正确的类型,但在额外的数组层或其他类型中)。

我的最后一次尝试是使用这个额外的代码,通过递归遍历数组:

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

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

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

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 ()

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

【问题讨论】:

  • 那是你的实际缩进吗?在你解决了这个问题之后,我建议你去Code Review
  • @Zeta 不是,但 ghci 一直在抱怨标签

标签: haskell types io list-comprehension monads


【解决方案1】:

您正在寻找一个名为 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.");
};

【讨论】:

    【解决方案2】:

    应该是这样的

    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}
    

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

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

    你也可以用列表推导式来写,

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

    sequence_ :: Monad m =&gt; [m a] -&gt; m () 将动作列表转换为一系列动作,丢弃其结果并最终生成()sequence_ = foldr (&gt;&gt;) (return ())。和sequence_ (map f xs) === mapM_ f xs,所以最后都联系在一起了。

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2012-08-31
        • 1970-01-01
        • 2018-08-25
        • 1970-01-01
        • 2020-11-16
        • 2019-02-14
        • 1970-01-01
        • 1970-01-01
        • 2013-01-26
        相关资源
        最近更新 更多