Home > OS >  Haskell Exercise Mooc FI Do notation
Haskell Exercise Mooc FI Do notation

Time:12-26

This is the exercise from https://haskell.mooc.fi/ training

-- Ex 5: define the IO operation readUntil f, which reads lines from
-- the user and returns them as a list. Reading is stopped when f
-- returns True for a line. (The value for which f returns True is not
-- returned.)
--
-- Example in GHCi:
--   *Set11> readUntil (=="STOP")
--   bananas
--   garlic
--   pakchoi
--   STOP
--   ["bananas","garlic","pakchoi"]

readUntil :: (String -> Bool) -> IO [String]
readUntil f = todo

Would you be able to provide me a hint / solution using do notation ? I am a beginning with the do notation and the "conditional logic" as well as looping is too complex for me at the moment.

Thank you so much

CodePudding user response:

With only do-notation and conditional statements I found the following solution:

readUntil :: (String -> Bool) -> IO [String]          
readUntil f = do x <- getLine; 
                 if f x then (return []) else (do k <- readUntil f
                                                  return (x : k))

The function first reads one line with getLine and then checks whether (f x) is true. It then returns just the empty list. We can't just write ... if f x then [] ... because [] has not the type IO [String] but just [String]. To make [] the type IO [String] we can use the function return or pure but with do-notation I use the return function, because it is included in the Monad typeclass. If f x equals False we then use a second do-block to recursively call the function again and again until we get an Input for which f x == True and therefore returns the empty list. The do-notation is necessary because k must have type [String], but readUntil has the type IO [String]. We can't use the : ("cons") operator with object of type IO String and therefore can't generate the list we want. We then add x to the list k of all our other inputs and return it.

  • Related