[Haskell-beginners] Problems with one of my first examples

Jeff C. Britton jcb at iteris.com
Mon Dec 15 17:26:11 EST 2008

Thanks, Michael.

Ok, I understand most of what you did, but ...

do nums <- askForNumbers; map sqrt nums

ERROR - Type error in final generator
*** Term           : map sqrt nums
*** Type           : [Integer]
*** Does not match : IO a

do nums <- askForNumbers; printList nums  -- works fine




I have started reading "Yet Another Haskell Tutorial" by Hal Daum´e III which can be found here

One of the early examples in section 3.8 pg. 35
is this

askForWords = do
 putStrLn "Please enter a word:"
 word <- getLine
 if word == ""
   then return []
   else do
     rest <- askForWords
     return (word : rest)

I want to print the returned list and everything I try fails.

I have tried the following:

printList l =
 if length l >= 1
   then do putStrLn (head l)
           printList (tail l)
   else putStrLn("")

f = printList askForWords

and I get
Expression     : printList askForWords
*** Term           : askForWords
*** Type           : IO [[Char]]
*** Does not match : [[Char]]

I believe one of the following will work for you:

f = askForWords >>= printList
f = do
        words <- askForWords
        printList words

The exercise right below this asks for a very slight modification to read numbers instead.

However, I am confused about how to convert strings to numbers.
If I type in the hugs interactive console
read "5" + 3 --> 8     -- ok perfect

read "5" gives
ERROR - Unresolved overloading
*** Type       : Read a => a
*** Expression : read "5"

Yet page 33 of the tutorial has the following code:
doGuessing num = do
 putStrLn "Enter your guess:"
 guess <- getLine
 let guessNum = read guess  -- ok in let stmt, but not at repl prompt?

The problem here is type inference. The statement read "5" has type "(Read a) => a", which basically means anything that implements the class "Read." When you do read "5" + 3, the read "5" gets the type of the 3. I assume that in the latter case, you use the expression guessNum in a way later on that the compiler can infer its type. 

Anyway I take the info that has been presented and create this function:
askForNumbers = do
   hSetBuffering stdin LineBuffering
   putStrLn "Give me a number (or 0 to stop)"
   numStr <- getLine
   let num = read numStr
   if num == 0
       then return []
       else do
           rest <- askForNumbers
           return (num : rest)

However, when I try to use it, like say

map sqrt askForNumbers

ERROR - Type error in application
*** Expression     : map sqrt askForNumbers
*** Term           : askForNumbers
*** Type           : IO [Integer]
*** Does not match : [a]

Similar to above, try this:
do nums <- askForNumbers
    map sqrt nums


Is there a way to write printList to handle Strings or numbers?
Or should I write
printList (map show askForNumbers)

Note: you should probably do this using mapM_, but for simplicity, I'll do it using explicit recursion:

printList [] = putStrLn "" -- or return () if you don't want the extra blank line
printList (x:xs) = do putStrLn (show x)
                      printList xs

If you have any questions about how these worked, let me know!


More information about the Beginners mailing list