At first, everything goes well. He’s impressed by the fact that you don’t have to constantly compile code to see the effects of your program. But after using the REPL as a calculator for a few minutes, he decides to check out how you write Hello World. This is where things start going downhill. He notices that the chapter on I/O is tucked away in the Advanced section.

When the trees were tall and dwarves roamed about in the forest, I was a wee tot tinkering about with MS-DOS .bat files. These were the days before there was a dial-up BBS around my area, let alone any dreams of the Internet. I’d heard of BASIC, but I didn’t have a compiler (later I got one), so I went the bizantine way of writing dozens of batch files calling each other conditionally using IF ERRORLEVEL. Evidently, not all was factible to do in that scheme (it could be argued that a gazillion batch files makes for a Turing-complete system, but what I had was complex enough for an 8-year-old). Help gradually came in the form of little .EXE files that did things — sorts, file concatenation, some better form of conditionals.

I eventually got someone to pirate me a copy of BASICA.EXE — and then I could program the games I had in my head. The infatuation must have lasted a few months; after that, I had exhausted all the little programming ideas a 9-year-old can have. But I had concocted a couple of cool little games.

Fast-forward. It’s three years ago, and after seriously dicking around with Matlab and getting the computer to do cool stuff like recognize tiny digit bitmaps with a simple backprop net (that I wrote myself, because I couldn’t make sense of the language in the NN module) or optimizing some routes with GAs, I thought again this programming thing was kind of cool. So I loaned a copy of the K&R manual on C and went home print “Oh bitty box!” with gcc.

Later that day, I went to ##c at freenode.net and asked what was only natural to me given my first experiences in trying to get something done with a computer: I wanted to know how to go about reading from stdin, applying a function and writing to stdout. I was told “well, there’s a lot you need to know before doing that”. So I dropped C. From my particular point of view, imperative language tutorials are severely flawed because they tuck how to operate the basic Unix form of program interaction in the “Advanced” section.

In case you’re curious, this is Haskell code for processing data from stdin with the_Big_function and writing to stdout:

main = interact the_Big_function

Now all you need to do is, you know, actually build the damn house and choose curtains later.

What my experience with batch files had taught me is that what programming is really all about is transforming pieces of data. It happens that some of the most visible examples of that are somewhat contrived, as they involve transforming Unix API instructions into bare-metal machine code (operating systems) or entire computer-states into next computer-states (gotos, for-loops, continuations, etc). But in a well-designed language, you should be able to focus on your problem domain, solve it well and fix the curtains later.

That’s what C programmers need to focus on if they want to learn Haskell: data-driven programming. Monads will come about at some point like the natural application of data-driven programming they really are. In the meantime, while you’re taking breaks from writing the coolest programs employing all the fancy data-structures in the Data.* hierarchy, playing from the REPL and maybe compiling a Unix pipe filter or two with main = interact the_Big_function, you can gradually read the best, if somewhat abstruse-looking in the beginning from all the commutative diagrams, monad tutorial out there.

Keep this in mind: a Haskell program is a list of equations transforming data structures. The rest will come, and if you’re smart enough to grok pointers (what the hell are that?), you will easily grok monads when they come up naturally as a Haskell structure like any other, defined in Haskell itself, no-answers-no-surprises.

I guess times have changed. These days, when you have pick up a book about an imperative language (Ruby, Java, Python), most people can’t wait to get past simple console programs and start to build GUIs. If anything, Haskell tutorials are the ones most likely to delay talking about IO.

interact has some subtleties you haven’t discussed so it’s not all beer and skittles.

This isn’t so much a distinction between imperative and functional languages, as it is between high- and low-level languages. In Perl, for instance, writing Unix pipes is trivial: while () {
print some_function($_);
}

Or just invoke perl with the -p switch, to wrap the whole program with “while () { … print $_; }”. Note that that’s actually a better Unix citizen than something written with interact, as it does the Right Thing with respect to files specified on the command-line, Ctrl-D, etc. Writing pipes is also pretty trivial in Ruby, Python, etc. It’s nontrivial in C not because it’s imperative, but because it’s low-level – because you need to mess around with strings as pointers to arrays of chars, and so on.

Come on, don’t be so abstract – one could at least say that the big function (or bla) needs to map between string and string (:t bla … bla :: [Char] -> [Char])
and the whole input is treated as a single string. if you’d like to get every string that is separated by a new line, you’ll have to do a bit more work…

Recent Posts

Dr. Syntaxfree

Dr. Syntaxfree has no PhD and shouldn't call himself a "doctor", but does so for amusement value anyway. An unemployed (ok, graduate student) econopundit by day, he's been progressively obsessed about Haskell to the point he often can't fathom not working on it. A jack-of-many-trades, he has an unusual CS background in that he knows no imperative programming at all, he hopes to be both helpful to those less knowledgeable than him and illustrative to the really smart people trying to understand the mentality of a common man trying to tackle functional programming.

Licenses

All rights reserved for textual content. A specific exception is granted to wikis hosted in the haskell.org domain; any text or code can be freely copied to such pages. All code is otherwise released under the LGPL.