The Decent Way to Learn Functional Programming

This entry is the second one in a series of blog posts about Agda. It describes the most boring method of learning something called "functional programming". The method is designed to be a fast way for people with perseverance (and masochistic propensity) or background in maths and/or computer science (and a hard humiliating way for everyone else).

As you can deduce from the abstract I’ve got into the mood of making a whole series of blog entries about Agda. It wouldn’t be quite as entertaining if I decided to start with Agda basics or, even worse, functional programming basics. There’s already a ton of great resources committed to that (see the rest of this entry). That’s why this series is going to be about things beyond Dependently Typed Programming in Agda (also known as “The Agda Tutorial”), mostly about Agda’s standard library and idioms.

But let me start with a bit of philosophy.

A bit of philosophy

In my view, computer science is rather fascinating field where constructive maths could be constructively used. I don’t know any other domain of knowledge where abstract structures could be used to affect real world so directly, e.g. “Okay, here are some operations on monoids. Now, we do blah-blah-blah and we get a phone book!” No joking. I’m sure, sometime it would be possible to teach most of the maths with the elegant (like Agda) and general (like Isabelle) proof assistants. This’ll give students the “feel” of maths right under their finges.

Computer science has this “feeling” property right now and, as far as I can see, it tempts teachers (guides/textbooks’ authors/blog writers) to use it to joy students (readers) with fast visible results. It’s a drug, don’t overdose. “But what’s wrong with impressing people with small useful examples while teaching them The Really Good Things on the way?”, you may ask. Learning becomes linear where it should be exponential (i.e. “the more you already know the faster you learn”).

One can’t teach everything in a fascinating way while keeping decent speed. Some things are just not meant to be fascinating by themselves, while the combination of two or more of them may be so really awesomely cool.

Things become worse and worse while learner’s experience with the field (or with related fields) grows. Virtually every book, tutorial or blog entry will repeat everything learner already heard somewhere and then (maybe) add some infinitely small portion of a new knowledge. The only way out from this never ending loop of rereading already known things lies in specialized literature and help from experts.

For example, once I became interested in modern state of computer graphics (beyond the fixed pipeline). I tried to read some fresh OpenGL tutorials, but they all start from concrete APIs (which is fine if I’d wanted to write my CG equivalent of “Hello, World!” as soon as possible, but I didn’t and I’d known most of that already) and then (hopefully) abstract them away for the overall picture. That’s a long story. Luckily, an occasion gave me a chance to have a dinner with a former university classmate who works in CG field. He knew what I had already known and explained everything I was interested in (the overall picture, what GPUs really do, how it’s wrapped into different APIs (DirectX, OpenGL and extensions), texturing, lighting, shadowing, shaders and etc), all in thirty minutes.

This is the reason why I think university education will not rot away. Even if you have all the books and all the internet, good teacher could save you years of scanning through them.

Teach yourself the functional programming

Said that, I’m sure, if you really want to teach yourself real functional programming, you shouldn’t entertain yourself too much with different tutorials which promise to show you yet another cool example application of some functional thing. By the way, this is why I think cherry-picking features from functional to imperative languages won’t work. I have a formal reason which, more or less, states that you’re just going to make your language into a mess no compiler could analyze and optimize (examples are left as an exercise to the reader), but informal philosophical reason is that you just fooling around with fascinating features when you need a solid theoretical base, and so you’ll never be able to compete with a language that has one.

In the next entry about Agda I’ll jump just after The Agda Tutorial. If you are not comfortable with the functional programming in general or with Agda in particular, I recommend you to build a solid base first. Stop entertaining yourself with cute functional example programs (this series of blog entries included). Get to the theory.

(This doesn’t mean you shouldn’t entertain yourself with tutorials about cool functional things at all. But The Base goes first.)

Let me list some resources I find extremely helpful in those goals. I’ll update this entry if I stumble upon something better than listed here.

Start from Logic and Lambda Calculus

Suppose you don’t know anything about functional programming at all, but you do have some mathematical background (e.g. one or two years of university education), abstract thinking and enough patience not to drop everything before you start getting visible results.

This is not how I teach students, because they are lazy and I have to mix some entertainment (cute examples with hand waving and no formal proofs of discussed properties are the drugs of CS, there are even whole churches committed to some of them, e.g. “software patterns”) in there. But this is exactly the way I was teaching myself.

It just happens that the most awesome book about functional programming I know is out of print and available for free from Simon Thompson’s (author) web site. At first, I would recommend to read first 50 or so pages of it. You may skip proofs if you want, but ask yourself a question “Why does this property matters?” about each of them (e.g. “Why does the independence from the order of reduction matters?”).

While I was an undergraduate student I had been doing all my assignments (and courseworks) in Haskell. Even if assignment explicitly said it was to be done in other language I would contact a teacher and ask for a permission to do it in Haskell. This is the only way to learn it quickly. Practice.

Write at least:

interpreter for untyped lambda calculus,

some numerical code with visualisation (Cairo or OpenGL), e.g. numerical differentiation (visualizing liquid dynamics is fun) or roots of complex polynomial (you can use resulting fractal pictures as a desktop backgrounds),

a HTTP web server, serving static files, or any other daemon working with clients.

a parser for untyped lambda with Parsec, connect it with previously written interpreter.

All of these combined shouldn’t take more than three days if your maths and system programming background is ok, but they’ll blow your mind. Also, they may sound more difficult than they really are.

But beware, you don’t necessarily need to become a master of Haskell to start with Agda. On the other hand, after some Agda experience most of Haskell becomes trivial. So, you may stop as soon as you got comfortable.

Get back to the Type Theory

Get back to Thompson’s book, read and understand everything you can. There is also a popular but not so cool Pierce’s book (not free). Read it too. Interleave and iterate these two with google and practice (invent and implement programs in hypothetical languages based on these theories, write interpreters for them in Haskell) until you understand most of the topics.