During the last two months, I taught an elective course on introductory functional programming. The nominal target group was third-year information technology undergrads, but in practice the student body consisted of everything from second-years to almost-done masters students. All had taken at least a year’s worth of general programming courses (taught in Java most recently, earlier in C++), a full semester’s worth of data structures, a half-semester of automata and grammar theory and some mathematics.
I have enough teaching experience (been teaching two courses a year since 2002) to know my faults. My biggest fault is that I routinely underestimate the difficulty and laboriousness of tasks I set for my students. My second biggest fault is that if I am not careful, I can easily revert to reciting reference material, that is theoretical definitions, instead of giving a tutorial. I am better at avoiding the latter fault than the former, although when I have little time to prepare, the latter fault will, too, manifest itself.
Knowing these faults, I tried to plan this course so that there would not be such trouble.
Reading Baen books, I have learned a military saying: Battle plans never survive contact with the enemy. I found myself in a similar situation: my course plan did not survive contact with the actual teaching situation. The broad outlines of what I was going to teach held mostly. Other than that, it ended up being a very different course than I had originally envisioned.
I started by giving a crash course on Haskell IO: how to write simple text-line-based interaction in Haskell. The idea was to introduce early the part of Haskell that many people think is hard but is actually quite easy, by explicitly drawing on the students’ imperative programming background. After IO, I ended up trying to give the students a broad, working knowledge of pure functional programming in Haskell, starting with first-order list processing and further discussing topics like parsing, persistent data structures, higher-order list processing, et cetera. I found that it was hard to give any of the topics proper room time-wise, as the basic concepts of functional programming are somewhat circularly related.
At this time, the students complained that the course is hard, and many dropped out. They shouldn’t have; we had covered the main topics of the course in half the time. I could then use the rest of the time to go over the topics again from a different point of view, and give them time and tools to integrate it all to their own internal know-how databases. In the latter part of the course, on the surface we discussed Haskell metacircularly, but that was mainly a tool to reinforce the stuff done earlier in the course.
Of course, my exercises were a little on the harder side. I ended up lowering official expectations about how much of the exercises the students were expected to solve, and that seems to have helped. Of the 20 people who took the first exam, 18 passed.
The advanced course starts in a week or two.