I have been learning Haskell for few months on my own now by doing some exercises I found on some lecturers site, and I stumbled upon this one and cannot figure how to solve it.
There are two tasks that are kinda "connected". I solved the first one with ease, but don't really understand how to do the other one.
Here's the first one:
Exercise 2. (Recall IO programming in Haskell and the do notation)
Write a recursive function
sumInts :: Integer -> IO Integer
that repeatedly reads integer numbers from IO until the number 0 is given. At that point, the function should return the sum of all the entered numbers plus the original (default) value, which is given as a function parameter.
I solved this one this way:
getInt :: IO Integer
getInt = do
s <- getLine
return (read s)
sumInts :: Integer -> IO Integer
sumInts input = do
x<-getInt
if x==0 then return input else (x+) <$> sumInts input
It was pretty easy to do. Here's the other one, the one I cannot understand:
Exercise 3. Generalize the previous IO interaction into a higher order function
whileIO :: IO a -> (a -> Bool) -> (a -> a -> a) -> a -> IO a
which, for the given reading IO action, termination condition, folding function, and the original value, returns the required IO action. Check that for some values of getIO, condF, foldF, we can redefine sumInts as
sumInts = whileIO getIO condF foldF
Would love some help with this one. :)
Hint:
try to generalize your code, making pieces of it as parameters instead of hardcoding them. For instance, replace the getInt
with a more general getIO
parameter.
sumInts :: IO Integer -> Integer -> IO Integer
sumInts getIO input = do
-- ^^^^^
x<-getIO -- <------
if x==0 then return input else (x+) <$> sumInts input
Then replace x==0
with a generic predicate.
Then replace (x+)
using a generic folding function.
And so on.
At the very end you'll get the wanted whileIO
, and you can also give it the more general type suggested by the exercise.