I want to read a list of strings separated by newlines from STDIN until a newline is witnessed, and I need a type action IO [String]
. Here's how I would do it with recursion:
myReadList :: IO String
myReadList = go []
where
go :: [String] -> IO [String]
go l = do {
inp <- getLine;
if (inp == "") then
return l;
else go (inp:l);
}
However, this method of using go hides readability and is so common that, ideally, I would like to abstract it.
So this was my attempt:
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)
I assume there is some default implementation of this whileM
or something similar already. However, I cannot find him.
Can someone point out what is the most natural and elegant way to solve this problem?
source
share