Working through Programming in Haskell (Second Edition) by Graham Hutton, I just managed to solve exercise 10.5 (page 138). The task is to write a function adder :: IO ()
that reads n
numbers (to be defined interactively), sums them up, and prints the result, like so:
> adder
How many numbers? 3
5
4
6
The total is 15
The functions readInt
and readLine
are already given as:
readInt :: IO Int
readInt = do
line <- readLine
return (read line :: Int)
readLine :: IO String
readLine = do
c <- getChar
case c of
'\n' -> return []
_ -> do
cs <- readLine
return (c:cs)
So I just had to write the adder
function:
adder :: IO ()
adder = do
putStr "How many numbers? "
n <- readInt
ns <- sequence [readInt | _ <- [1..n]]
sum <- sumUp ns
putStr $ "The total is " ++ (show sum) ++ "\n"
sumUp :: [Int] -> IO Int
sumUp xs = return $ foldl (+) 0 xs
I'm almost happy with my solution, but I'd just like to inline the sumUp
function. However, I have no idea how to do it.
How can I inline a [a] -> IO a
function into a do
block?
There is no need to use return
here, we can use sum :: (Foldable f, Num a) => f a -> a
to sum up the numbers:
adder :: IO ()
adder = do
putStr "How many numbers? "
n <- readInt
ns <- sequence [readInt | _ <- [1 .. n]]
putStr $ "The total is " ++ (show (sum ns)) ++ "\n"
We can also repeat readInt
through replicateM :: Applicative m => Int -> m a -> m [a]
:
import Control.Monad(replicateM)
adder :: IO ()
adder = do
putStr "How many numbers? "
ns <- readInt >>= (`replicateM` readInt)
putStrLn $ "The total is " ++ (show (sum ns))
as for readInt
, this can be implemented as:
readInt :: IO Int
readInt = readLn