Reputation: 301
I'm making a function readUntil
that reads lines from user. Reading stops when f
returns True for a line. Then the lines are returned as a list (the line that returned True is not included in that list). Here's what I have at the moment (some really raw/pseudo code now, excuse me):
readUntil :: (String -> Bool) -> IO [String]
readUntil f = fmap reverse (go []) where
go xs = do
x <- getLine
if f = True then return xs
else go (x : xs)
I would also like to make readUntil
recursive (or implement a recursive helper function).
Upvotes: 1
Views: 1078
Reputation: 961
I've included a small example below. You're pretty much at the solution. The important bit is just remembering how you'd generate a non-monad recusive list, then just putting that in the monad.
collectUntil :: (Monad m) => m a -> (a -> Bool) -> m [a]
collectUntil act f = do
x <- act
if f x
then return []
else (x:) <$> collectUntil act f
readUntil :: (String -> Bool) -> IO [String]
readUntil = collectUntil getLine
Upvotes: 1