newbie - IO issues (of course)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

newbie - IO issues (of course)

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)

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  

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: newbie - IO issues (of course)

Jason Dagit
On 6/23/06, Geoffrey King <[hidden email]> 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)

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
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: newbie - IO issues (of course)

Bulat Ziganshin-2
In reply to this post by Geoffrey King
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:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: newbie - IO issues (of course)

Stepan Golosunov
In reply to this post by Geoffrey King
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)
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe