
I have been work my way through "Haskell The Craft of Functional Programming", all was fine until IO (chapter 18). That is causing me bafflement. I am trying to write a totally trivial program that reads a series of integers from the console until it gets a zero, then returns the series of integers as a list. I am down to randomly editing my code, never a good sign. Any clues would be appreciated, My code so far, which clear doesn't work, is: getInt :: IO Int getInt = do putStr "Enter number (zero to quit)" line <- getLine return (read line :: Int) anIntList :: [Int] anIntList = do let n = getInt if n == 0 then return [] else return (n : anIntList) ps: even a simple version that returns an Int i can't get to work. anInt :: Int anInt = do n <- getInt return n

On 6/23/06, Geoffrey King
I have been work my way through "Haskell The Craft of Functional Programming", all was fine until IO (chapter 18). That is causing me bafflement.
I am trying to write a totally trivial program that reads a series of integers from the console until it gets a zero, then returns the series of integers as a list.
I am down to randomly editing my code, never a good sign. Any clues would be appreciated, My code so far, which clear doesn't work, is: getInt :: IO Int getInt = do putStr "Enter number (zero to quit)" line <- getLine return (read line :: Int)
I haven't tested your code or my proposed changes, but let me step through what you have and offer up explanations of what I think is going wrong. So here, things look pretty good with getInt. getInt has type IO Int, which makes sense because you do some work in the IO monad construct a value and return it. Since you can't escape the IO monad, getInt returns an Int which is wrapped up in the IO monad.
anIntList :: [Int] anIntList = do let n = getInt if n == 0 then return [] else return (n : anIntList)
Okay, so lets start with the let. What is the type of n? Well, it's IO Int because that's the type of getInt. But, IO Int isn't a number so you can't do the test in the if. Otherwise, your code looks pretty good.
ps: even a simple version that returns an Int i can't get to work. anInt :: Int anInt = do n <- getInt return n
Now you're getting closer. But, you do work in the IO monad and construct a value and return it, so your type signature must be wrong. It must be the case that anInt :: IO Int. I see here that you know how to grab 'unwrap' a value in the IO monad and work with it (the line, n <- getInt), you should try doing this above where you have 'let n = getInt'. You may also want to read these fine web pages: http://www.haskell.org/hawiki/MonadsAsContainers http://www.nomaware.com/monads/html/index.html You're so close, I expect you'll have it figured out before I can hit send :) HTH, Jason

Hello Geoffrey, Saturday, June 24, 2006, 8:38:31 AM, you wrote:
getInt :: IO Int getInt = do putStr "Enter number (zero to quit)" line <- getLine return (read line :: Int)
this procedure is fine, although there is specific function to read data of any type, which is just equivalent to getLine+read. using it, we can make routine even smaller: getInt :: IO Int getInt = do putStr "Enter number (zero to quit)" readLn
anIntList :: [Int] anIntList = do let n = getInt if n == 0 then return [] else return (n : anIntList)
IO monad cannot escape, so you can't use inside non-IO function (anIntList) an IO function (getInt) this have very simple explanation - Haskell is pure language, that meant that functions allways return the same results with same arguments. your anIntList don't have arguments, so it should return the same data on each call, really it's type signature meant that it just a constant! on the other side, return type "IO a" means that function can be called in IO monad context (such as inside "main") and may return different results even with the same arguments as conclusion, anIntList should have type "IO [Int]". try to write it yourself, i will help if you need it ps: i definitely will write wiki "introduction to monads and i/o" next week, it is so frequent source of beginner's troubles! -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

On Sat, Jun 24, 2006 at 02:38:31PM +1000, Geoffrey King wrote:
I have been work my way through "Haskell The Craft of Functional Programming", all was fine until IO (chapter 18). That is causing me bafflement.
I am trying to write a totally trivial program that reads a series of integers from the console until it gets a zero, then returns the series of integers as a list.
I am down to randomly editing my code, never a good sign. Any clues would be appreciated, My code so far, which clear doesn't work, is: getInt :: IO Int getInt = do putStr "Enter number (zero to quit)" line <- getLine return (read line :: Int)
anIntList :: [Int]
anIntList is an IO action which reads a list, and as such has type IO [Int], not [Int].
anIntList = do let n = getInt
You should use "n <- getInt" to perform getInt and read integer into n. "let n = getInt" just says that n is an IO action which reads integer, not that integer itself.
if n == 0 then return [] else return (n : anIntList)
As anIntList is not a list this won't work. You should perform anIntList and then use its result: do list <- anIntList return (n : list)
participants (4)
-
Bulat Ziganshin
-
Geoffrey King
-
Jason Dagit
-
Stepan Golosunov