简体   繁体   English

如何通过IO操作运行列表

[英]How do I run through a list with an IO operation

So I'm writing a program that checks for every line of a .txt file whether it is a palindrome or not, 所以我正在编写一个程序来检查.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));
}

But instead of singleWord (head (lines content)) I need to run the singleWord through the entire list. 但是我需要在整个列表中运行singleWord而不是singleWord (head (lines content))

The problem is that with map or normal list comprehension I always get a ton of varying errors all to do with lines content (which should be an array of Strings or IO Strings) apparently always being the type I don't want (I've tried messing around with type declarations on that forever, but it keeps being the wrong type, or the right one but in an extra array-layer or whatever). 问题是,对于map或普通列表理解,我总是会遇到大量不同的错误,这些错误与lines content (应该是字符串或IO字符串数组)有关,显然总是我不想要的类型(我是我一直试图弄乱类型声明,但它仍然是错误的类型,或者是正确的类型,但在额外的数组层或其他方面)。

My last attempt is to walk through the array with recursion, with this little extra code: 我的最后一次尝试是通过递归来遍历数组,这个额外的代码:

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

which I can't typecast correctly no matter what. 无论如何我无法正确地进行类型转换。

It's supposed to replace the singleWord (head (lines content)) in main , and if I try anything with typeclassing, like 它应该更换singleWord (head (lines content))main ,如果我尝试任何与typeclassing,像

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

I get 我明白了

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

or some other stuff that won't fit together. 或其他一些不适合的东西。

You're looking for a function called mapM_ . 您正在寻找一个名为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.");
};

That should've been 那应该是

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

or better yet, 或者更好,

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

and call it as walkthrough (lines content) in your main do block. 并在主do块中将其称为walkthrough (lines content)

As others have pointed out, walkthrough is the same as mapM_ singleWord . 正如其他人所指出的, walkthroughmapM_ singleWord相同。

You could also write it with a list comprehension, 你也可以用列表理解来编写它,

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

sequence_ :: Monad m => [ma] -> m () turns a list of actions into a sequence of actions discarding their results and producing the () in the end: sequence_ = foldr (>>) (return ()) . sequence_ :: Monad m => [ma] -> m ()将一个动作列表转换为一系列动作,丢弃它们的结果并在最后生成()sequence_ = foldr (>>) (return ()) And sequence_ (map f xs) === mapM_ f xs , so it all ties up in the end. sequence_ (map f xs) === mapM_ f xs ,所以它们最终都会mapM_ f xs

Use mapM_ singleWord (lines content) . 使用mapM_ singleWord (lines content) For the sake of simplicity, think of mapM_ as. 为简单起见,将mapM_视为。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM