Yes, they are. That's what perhaps Neil Mitchell means by

mapM_ putStrLn == putStr . unlines

And whether the trailing newline is to be called the last blank line depends upon the convention; The string that is output in both the cases contains a single newline character. Are you calling that a blank line at end?

And I actually meant to reply to haskell-cafe as well; omitted haskell-cafe by mistake. Anyway, you got the same answer from two people! This time I am including haskell-cafe in the recipients.

Regards,
Abhay

On Mon, Apr 14, 2008 at 4:05 PM, Benjamin L. Russell <dekudekuplex@yahoo.com> wrote:
Abhay Parvate,

Thank you; that answered my question.

Then, the following two lines of code should be
equivalent:

In hanoi.hs:
hanoi n = mapM_ putStrLn (hanoi_helper 'a' 'b' 'c' n)

In hanoi_unlines.hs:
hanoi n = putStr (unlines(hanoi_helper 'a' 'b' 'c' n))

I tested them both out on WinHugs (Version Sep 2006);
they both generated one blank line at the end.

Benjamin L. Russell

--- Abhay Parvate <abhay.parvate@gmail.com> wrote:

> unlines puts newline after each string; putStrLn
> puts newline after the
> given string. As a result, the output contains two
> newlines in the end. You
> can use putStr instead, since the resultant string
> from 'unlines' will have
> a newline at the end.
>
> On Mon, Apr 14, 2008 at 2:12 PM, Benjamin L. Russell
> <dekudekuplex@yahoo.com>
> wrote:
>
> > Ok; much better.  Here's my new type signature and
> > definition:
> >
> > hanoi.hs:
> > hanoi :: Int -> IO ()
> > hanoi n = mapM_ putStrLn (hanoi_helper 'a' 'b' 'c'
> n)
> >
> > hanoi_helper :: Char -> Char -> Char -> Int ->
> > [String]
> > hanoi_helper source using dest n
> >    | n == 1 = ["Move " ++ show source ++ " to " ++
> > show dest ++ "."]
> >    | otherwise = hanoi_helper source dest using
> (n-1)
> >
> >                  ++ hanoi_helper source using dest
> 1
> >                         ++ hanoi_helper using
> source
> > dest (n-1)
> >
> > Then in WinHugs (Version Sep 2006):
> >
> > Hugs> :load hanoi.hs
> > Main> hanoi 2
> > Move 'a' to 'b'.
> > Move 'a' to 'c'.
> > Move 'b' to 'c'.
> >
> > Great!
> >
> > One minor question:  I tried out both of your
> > following suggestions:
> >
> > >    > mapM_ putStrLn (hanoi 2) -- outputs each
> move
> > > in a new line
> > >    > putStrLn (unlines (hanoi 2)) -- same as
> > > previous line
> >
> > and discovered that putStrLn with unlines (the
> lower
> > option) in fact generates one extra blank line at
> the
> > end.  Just curious as to why....
> >
> > Benjamin L. Russell
> >
> > --- Tillmann Rendel <rendel@daimi.au.dk> wrote:
> >
> > > Benjamin L. Russell wrote:
> > > > but got stuck on outputting newlines as part
> of
> > > the string;
> > >
> > > quoting is done by the show function in Haskell,
> so
> > > you have to take
> > > care to avoid calling show. your code calls show
> at
> > > two positions:
> > > (1) when you insert the newline into the string
> > > (2) when you output the string
> > >
> > > with respect to (1):
> > >
> > > you use (show '\n') to create a newline-only
> string,
> > > which produces a
> > > machine-readable (!) textual representation of
> '\n'.
> > > try the difference
> > > between
> > >
> > >    > '\n'
> > >
> > > and
> > >
> > >    > show '\n'
> > >
> > > to see what I mean. instead of using (show
> '\n'),
> > > you should simply use
> > > "\n" to encode the string of length 1 containing
> a
> > > newline character.
> > >
> > > with respect to (2):
> > >
> > > the type of your top-level expression is String,
> > > which is automatically
> > > print'ed by the interpreter. but print x =
> putStrLn
> > > (show x), so there
> > > is another call to show at this point. to avoid
> this
> > > call, write an IO
> > > action yourself. try the difference between
> > >
> > >    putStrLn (hanoi ...)
> > >
> > > and
> > >
> > >    print (hanoi ...)
> > >
> > > to see what I mean.
> > >
> > > Last, but not least, I would like to point out a
> > > different aproach to
> > > multiline output which is often used by Haskell
> > > programmers: The worker
> > > functions in this aproach produces a list of
> > > strings, which is joined
> > > together with newlines by the unlines function.
> In
> > > your case:
> > >
> > >    hanoi_helper :: ... -> [String]
> > >      | ... = ["Move " ++ ...]
> > >      | otherwise = hanoi_helper ... ++
> hanoi_helper
> > > ...
> > >
> > >    hanoi n = hanoi_helper 'a' 'b' 'c' n
> > >
> > > and in the interpreter one of these:
> > >
> > >    > hanoi 2 -- outputs a list
> > >    > mapM_ putStrLn (hanoi 2) -- outputs each
> move
> > > in a new line
> > >    > putStrLn (unlines (hanoi 2)) -- same as
> > > previous line
> > >
> > > Tillmann
> > > _______________________________________________
> > > Haskell-Cafe mailing list
> > > Haskell-Cafe@haskell.org
> > >
> http://www.haskell.org/mailman/listinfo/haskell-cafe
> > >
> >
> > _______________________________________________
> > Haskell-Cafe mailing list
> > Haskell-Cafe@haskell.org
> >
> http://www.haskell.org/mailman/listinfo/haskell-cafe
> >
>