1

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).

6
  • 2
    f = True. I'm a bit surprised to see such check. Commented Apr 21, 2018 at 12:43
  • @WillemVanOnsem I did a bit of a pseudo code to start with (since I'm kinda stuck), as in "check if f is True here". Sorry I should've explained it. Commented Apr 21, 2018 at 12:49
  • 1
    Well I have the idea that you are quite close to a valid solution. Here you want that f applied with parameter x is True, so I guess with a few hints you can come up with a solution. Commented Apr 21, 2018 at 12:53
  • I changed it to if f x == True and it works, thank you! Commented Apr 21, 2018 at 13:30
  • a == True has the same value as a Commented Apr 21, 2018 at 14:26

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.