Question about error message

Seth Kurtzberg seth@cql.com
Mon, 19 Aug 2002 10:15:11 -0700


Paulo,

Yes, that does help.  Also, it helps explain something else that I have been 
wondering about, which is why I'm sometimes able to eliminate an error 
message by adding a temporary and using the do construct to load a value into 
it.  Something like replacing:

     xyz (abc def)

with

    do temp <- abc def
         xyz temp

which appears to (at times) convert a value from "IO m" to "m" (or v.v.).

Now, since no good deed goes unpunished, let me toss another question (or two) 
at you.  Here is some code that only works with the do construct, and I can't 
see why it is necessary.  This occurs regardless of whether anything else in 
the program uses the do construct, so it isn't one of those cases where 
something that is called is monadic and thus the caller needs to be monadic 
as well.  The fragment is:

displaySolutions (x:[]) = displayOneSolution x
displaySolutions (x:xs) =
    do displayOneSolution x
         displaySolutions xs

Why is the "do" necessary for the second pattern?  If I leave it out, the 
compiler complains that I'm applying "displayOneSolution" to too many 
arguments, namely "x displaySolutions xs".  Parentheses don't help; then it 
just complains that I'm applying "(displayOneSolution x)" to too many 
arguments, namely "displaySolutions xs".  Other placements of parentheses 
change the error message but do not eliminate the problem.

If I add a semicolon after "displayOneSolution x" I get a syntax error from 
the parser.  Obviously something is going on here that I don't quite 
understand.

One last question.  What is the syntax to use in an IO environment to do 
nothing?  For example, I have a function of type "IO ()", with some patterns, 
and I want to add another pattern that accepts an empty list and, 
essentially, does nothing with it.  Do I use "return ()"?

TIA,

On Monday 19 August 2002 05:59, Paulo Sequeira wrote:
> Ok, you got me.
>
> My wording was not careful, so I must rectify.
>
> If you try
>
>     let xyz = do getLine in do p <- xyz; putStr p
>
> you'll see that in xyz I'm not really discarding the string read (you
> caught it later in p).
>
> Definitively, Alastair's explanation is more correct than mine and it
> didn't lead you to a misunderstanding.
>
> You must understand that do notation is mostly syntactic sugar. It is more
> familiar to write
>
>     do p <- getLine; putStr p
>
> than to write
>
>     getLine >>= (\ p -> putStr p)
>
> What I really mean by "discarding" was that, if you write
>
>    do getLine; stmt
>
> you would simply won't have at hand the line read in stmt because the value
> was not bound to any variable. Note that the previous line is equivalent to
>
>     getLine >> do stmt
>
> or, by the definition of >>
>
>     getLine >>= (\ _ -> do stmt)
>
> See it?
>
> Also, note that when you write
>
>     do getLine
>
> in GHCi, it is GHCi who is "discarding" the string. (mmm, would this last
> statement be also misleading?)
>
> Hope I'm now explaining myself better.
>
> Paulo.
>
> ----- Original Message -----
> From: Seth Kurtzberg <seth@cql.com>
> To: Paulo Sequeira <otro_paulo@hotmail.com>
> Sent: Saturday, August 17, 2002 7:25 PM
> Subject: Re: Question about error message
>
> > Paulo, and also Alastair,
> >
> > Thanks for the responses.  And, from a practical perspective, Paulo's
> > workaround is interesting (and also works).  But ...
> >
> > Wait a minute.  The type (according to GHCI) of both:
> >
> >     xyz = do getLine
> >
> > and
> >
> >     abc = do p <- getLine
> >                   return p
> >
> > is IO String.  And, in fact, both expressions indeed return the String
>
> part of
>
> > the IO String.  So (I'm playing devil's advocate here) you are asserting
>
> that
>
> > it is correct for one entity of type IO String to provoke different
>
> behavior
>
> > than another entity of type IO String.  All "IO String"s are not created
> > equal.
> >
> > I don't see, fundamentally, how it violates referential integrity or any
>
> other
>
> > functional programming principle to stick a value somewhere and not use
>
> it.
>
> > It might not be very intelligent, or useful, but that is irrelevant from
>
> the
>
> > theoretical perspective.
> >
> > And, the restriction has a negative impact on code reuse.  I shouldn't
>
> need to
>
> > define both "abc" and "xyz" in the above example, which do the same
> > thing, merely because sometimes I want the result and other times I
> > don't.
> >
> > On Saturday 17 August 2002 16:14, you wrote:
> > > Perhaps it will help if you recall the meaning of the do notation,
> > > according to the Haskell98 Report.
> > >
> > >     do {e} = e
> > >     do {e;stmts} = e >> do {stmts}
> > >     do {p <- e; stmts} =
> > >         let
> > >             ok p = do {stmts}
> > >             ok _ = fail "..."
> > >         in e >>= ok
> > >     do {let decls; stmts} = let decls in do {stmts}
> > >
> > >
> > > Note that "do p <-e" only has meaning when is followed by something
> > > else (e.g. an expresion). One way to explain it is that it only makes
> > > sense
>
> to
>
> > > introduce "p" to use it later (e.g. you are reading a string and
> > > binding
>
> it
>
> > > to "p" to parse it later). If you are only interested in the side
>
> effects
>
> > > of "getLine", you should write:
> > >
> > > main = do getLine
> > >
> > > This will effectively read a line and discard it afterwards. Try it.
> > >
> > > Paulo.
> > >
> > > ----- Original Message -----
> > > From: Seth Kurtzberg <seth@cql.com>
> > > To: <glasgow-haskell-users@haskell.org>
> > > Sent: Saturday, August 17, 2002 2:23 PM
> > > Subject: Question about error message
> > >
> > > > Hello, all
> > > >
> > > > There is an error message that I get from GHCI that I do not
>
> understand.
>
> > > > Usually it is caused by a syntax error or an indentation error, but I
> > > > have occasionally seen it in other contexts and I'd like to
> > > > understand what it
> > >
> > > is
> > >
> > > > trying to tell me.
> > > >
> > > > The message is that the last statement in a do construct must be an
> > >
> > > expression
> > >
> > > > (exact text below).
> > > >
> > > > I believe this occurs when the last statement in the do construct has
>
> a
>
> > > type
> > >
> > > > other than "IO ()".  The documentation (or perhaps Simon Thompson's
> > > > or
> > >
> > > Paul
> > >
> > > > Hudak's book; they get jumbled together in my mind) states that all
> > > > statements in a do construct have type "IO ()"; but this is clearly
>
> not
>
> > > > correct, as in:
> > > >
> > > >     do line <- getLine
> > > >         putStrLn line
> > > >
> > > > where the first statement has type IO String.
> > > >
> > > > Here is an example.  This code is useless but it is not obvious to me
>
> why
>
> > > it
> > >
> > > > is incorrect:
> > > >
> > > >     main = do line <- getLine
> > > >
> > > > producing the error:
> > > >
> > > > <interactive>:1: The last statement in a 'do' construct must be an
> > >
> > > expression
> > >
> > > > (This also limits the ability to enter monadic programming to the
> > > > interpreter.)
> > > >
> > > > TIA,
> > > >
> > > > --
> > > > Seth Kurtzberg
> > > > M. I. S. Corp
> > > > seth@cql.com
> > > > 1-480-661-1849 (GMT-7)
> > > >
> > > > _______________________________________________
> > > > Glasgow-haskell-users mailing list
> > > > Glasgow-haskell-users@haskell.org
> > > > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
> >
> > --
> > Seth Kurtzberg
> > M. I. S. Corp
> > seth@cql.com
> > 1-480-661-1849 (GMT-7)
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users@haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users

-- 
-----------------------------------
Seth Kurtzberg
M. I. S. Corp.
1-480-661-1849