writing a function to build a list of ints from user input

Galen Menzel galen@alumni.utexas.net
Tue, 6 May 2003 05:02:56 -0500


On Tue, May 06, 2003 at 09:05:46PM +0000, sashan wrote:
> I'm trying to write a function that builds a list from user input. This 
> is what I've come up with so far.
> 
> --a program that makes a list of numbers from user input
> makeList :: IO [Int]
> makeList = do s <- getLine             
>                      if read s /= 0 then return (read s:makeList) else 
> return []
> 
> However it fails with the following error:
> Couldn't match `[a]' against `IO [Int]'
>    Expected type: [a]
>    Inferred type: IO [Int]
>    In the second argument of `(:)', namely `makeList'
>    In the first argument of `return', namely `((read s) : makeList)'
> 
> It's trying to match a list, [a], with type IO [Int]. This causes it to 
> fail. How do I get around this?

This is happening because makeList returns IO [Int], whereas the (:)
operator or only defined over [a].  It doesn't work for the same
reason that you can't use getLine as a String.  This should work:

makeList :: IO [Int]
makeList = do s <- getLine
	      case read s of
		0 -> return []
		x -> do xs <- makeList
			return (x:xs)

I changed the if to a case so that (read s) doesn't get called twice.

Hope that helps.
galen