我想从 STDIN 读取由换行符分隔的字符串列表,直到看到新行并且我想要 IO [String]
类型的操作。这是我将如何使用递归来做到这一点:
myReadList :: IO String
myReadList = go []
where
go :: [String] -> IO [String]
go l = do {
inp <- getLine;
if (inp == "") then
return l;
else go (inp:l);
}
然而,这种使用 go 的方法掩盖了可读性,并且是一种非常常见的模式,以至于人们理想地希望将其抽象出来。
因此,这是我的尝试:
whileM :: (Monad m) => (a -> Bool) -> [m a] -> m [a]
whileM p [] = return []
whileM p (x:xs) = do
s <- x
if p s
then do
l <- whileM p xs
return (s:l)
else
return []
myReadList :: IO [String]
myReadList = whileM (/= "") (repeat getLine)
我猜这个
whileM
或类似的东西已经有一些默认实现。但是我找不到它。有人能指出处理这个问题的最自然、最优雅的方法是什么吗?
最佳答案
unfoldWhileM 与您的 whileM
相同,只是它采用一个 Action (不是列表)作为第二个参数。
myReadList = unfoldWhileM (/= "") getLine