Testing the Haskell ‘do’ block with getContents and putStr

I was curious about how the “input redirection” program on page 170 of Learn You a Haskell for Great Good (LYAH) worked, so I typed it into a file named do1.hs, with one additional line:

import Data.Char

main = do
    contents <- getContents
    putStrLn "dude"
    putStr $ map toUpper contents

The line I added is the putStrLn "dude" line.

I compiled it like this:

$ ghc do1.hs

Then I ran it like this:

$ ./do1 < do1.hs

Can you guess what the output was?

This space intentionally left blank so you can think about it ...

.

.

.

Here’s the output:

dude
IMPORT DATA.CHAR

MAIN = DO
    CONTENTS <- GETCONTENTS
    PUTSTRLN "DUDE"
    PUTSTR $ MAP TOUPPER CONTENTS

That’s pretty cool.

I ran this code because I wasn’t 100% sold on the description of the do block code on page 172, but the description is correct. The putStr and getContents functions have a lazy interaction that is, well, cool.

Follow-up: The same example in Scala

Hmph, I guess that code isn’t that exciting ... if I use the using construct that I described in the Scala Cookbook, that Haskell code is close to being the same as this:

using(Source.fromFile("/etc/passwd")) { source => {
    lazy val lines = source.getLines
    println("dude")
    lines.map(_.toUpperCase).foreach(println)
}}

In this code getLines returns an iterator. I’m actually interested in the Haskell hGetContents function, which LYAH says returns a Handle. At the moment I don’t know how that maps to Scala, as in I don’t know if a Haskell Handle is more similar to a Scala File or an Iterator.

Note that I put the lazy in there because I think that’s closer to what Haskell does. Also note that in Scala that last line can be written a little more directly like this:

lines.foreach(s => println(s.toUpperCase))

I think I was just confused with the Haskell code by the do block. For some reason I always want it to be a loop, which it is not.

(The using block isn’t necessary for this example, but it does automatically close the file, which is nice.)