Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The Haskell way to do IO Loops (without explicit recursion)?

I want to read a list of strings seperated by newlines from STDIN, until a new line is witnessed and I want an action of the type IO [String]. Here is 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 obscures readability and is a pattern so common that one would ideally want to abstract this out.

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 am guessing there is some default implementation of this whileM or something similar already. However I cannot find it.

Could someone point out what is the most natural and elegant way to deal with this problem?

like image 620
Agnishom Chattopadhyay Avatar asked Dec 05 '22 13:12

Agnishom Chattopadhyay


1 Answers

unfoldWhileM is same as your whileM except that it takes an action (not a list) as second argument.

myReadList = unfoldWhileM (/= "") getLine
like image 147
Hogeyama Avatar answered Mar 08 '23 01:03

Hogeyama