我如何 运行 通过一个 IO 操作的列表
How do I run through a list with an IO operation
所以我正在编写一个程序来检查 .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 ()
或其他一些不能组合在一起的东西。
使用mapM_ singleWord (lines content)
。为了简单起见,将 mapM_
视为。
mapM_ :: (a -> IO ()) -> [a] -> IO ()
您正在寻找一个名为 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.");
};
那应该是
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)
。
正如其他人所指出的,walkthrough
与 mapM_ singleWord
相同。
你也可以用列表理解来写,
walkthrough xs = sequence_ [ singleWord x | x <- xs]
sequence_ :: Monad m => [m a] -> m ()
将动作列表变成一系列动作,丢弃它们的结果并最终生成 ()
:sequence_ = foldr (>>) (return ())
。而sequence_ (map f xs)
=== mapM_ f xs
,所以最后一切都结束了。
所以我正在编写一个程序来检查 .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 ()
或其他一些不能组合在一起的东西。
使用mapM_ singleWord (lines content)
。为了简单起见,将 mapM_
视为。
mapM_ :: (a -> IO ()) -> [a] -> IO ()
您正在寻找一个名为 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.");
};
那应该是
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)
。
正如其他人所指出的,walkthrough
与 mapM_ singleWord
相同。
你也可以用列表理解来写,
walkthrough xs = sequence_ [ singleWord x | x <- xs]
sequence_ :: Monad m => [m a] -> m ()
将动作列表变成一系列动作,丢弃它们的结果并最终生成 ()
:sequence_ = foldr (>>) (return ())
。而sequence_ (map f xs)
=== mapM_ f xs
,所以最后一切都结束了。