Previous | Up | Next

Working Review of "Practical ML Programming with SML#" (Ohori, Ueno), CHAPTER 6

Techniques of designing and developing ML-style systems

This chapter is a really fun one to read and implement. It utilizes all of the concepts introduced in chapters 1 through 5, with the goal of creating a standalone program. The program in question is a tty-based game of Reversi.

A high-level breakdown of the chapter

The authors guide us in the design and implemenation of our game in three broad movements:

  1. Analyzing and designing the system using types
  2. Top-down implementation
  3. Considering the procedural and the declarative separately

Analyzing and designing the system using types

The first section shows us how to “think in types” to represent the domain of Reversi. The authors stay close to the KISS philosophy and select the most straightforward datastructures, such as the simple algebraic

datatype color = BLACK | WHITE

to represent the colour of pieces on the board, and a simple property list of ((x,y), color) tuples to represent their positions. There is a short discussion of the efficiency of different interger/word representations, but ultimately the plain vanilla int is decided upon, for clarity’s sake.

Then, considering only the types determined above, the authors sketch a high-level picture of how the various elements will ‘click together’ to model a game of Reversi.

Top-down implementation

The section titled “Top-down implementation” is an elegant demonstration of how to lean on the type system to guide us in writing concrete code. We start out by slowly fleshing out the “sketch” functions from the previous section so that they match their type signatures, leaving “notes” in place of missing lower-level functionality.

Then, we move on to making the “notes” into real code. We get to see things like the option type and various list operations (such as concat or filter) in a real-life program. By the end of this section, we have a complete “pure code” model of Reversi, which we can play around with in an interactive SML# session. But no stand-alone program exists yet.

While this section is very informative and unfolds in a nice logical progression, following the top-down methodology the authors advertise, I found two things lacking:

  1. The comment → code approach of drilling down into details doesn’t really allow for partially-written functions to compile. This weakens the didactic effect, as it makes it seem that the entire module comes out fully-formed out of Zeus’ proverbial head.

  2. Modeling the game as pure code is a boon for testing. I feel that this chapter was edited for brevity, with some kind of interactive-shell-based testing section removed. (We don’t see the play function in action!) It would have been even better if the built-in smlunit framework was used to build the pure model in a test-driven manner. Maybe I’ll revisit this idea later on.

Considering the procedural and the declarative separately

Here is where we get to wrap our decalarative core in a procedural outer shell, producing a stand-alone executable that plays Reversi. Again, as in the first section, the authors opt for the simplest possible implementation of their ideas, and the result is both elegant and understandable. It’s quite literally a textbook implementation of the pure/impure sandwich.

Some advanced discussion topics I’d like the authors to have explored:

Exercises

The exercises in this chapter are quite deep. Starting with improving the bare-bones TTY interface, through implementing a CPU opponent, all the way up to implementing a GUI for the game (using a later chapter as reference).

I have a working implementation of the game, including a super-crude CPU opponent, at pzel/reversi. Please check it out.

Previous | Up | Next