
comments inline...
module Main where
import IO
main = do hSetBuffering stdin LineBuffering words <- askForNumbers printWords words map read words putStrLn "The sum is" foldl (+) 0 words
as you noted "map read words" is a problematic line. The problem that GHC tells you about is that "map read words" creates a value of type (Read a) => [a], where but each line in an IO do block needs to have type IO a. THe "foldl (+) 0 words" line has the same problem; it's not an IO value. A trick you can use is to use "let" to bind a pure value inside a do block, see below. I seems to me that you are thinking that "map read" will alter "words" from a list of Strings to a list of Ints. This is a fundamental no-no in a pure functional language like Haskell. What you want is to create a new list of integers from your "words" list. The following changes makes your program work. main = do hSetBuffering stdin LineBuffering words <- askForNumbers printWords words --map read words let ints = map read words putStrLn "The sum is" --foldl (+) 0 words putStrLn (show (foldl (+) 0 ints))
askForNumbers = do putStrLn "Please enter a number:" text <- getLine if text == "" then return [] else if text == "0" then return [] else do rest <- askForNumbers return (text : rest)
This is pretty verbose and (IMO) hard to read. I'd probably write it this way: askForNumbers = do putStrLn "Pleas enter a number:" text <- getLine case text of "" -> return [] "0" -> return [] _ -> askForNumbers >>= return . (text:)
printWords [] = putStrLn "EOL" printWords (h : t) = do putStrLn h printWords t
This could also be more succinct with "sequence_", although increased redability is arguable. printWords x = sequence_ (map putStrLn x) >> putStrLn "EOL"