Previous    |   Up   |    Next

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

Let's read SML#で始める実践MLプログラミング

I am back to blogging. I have a couple half-written Erlang posts in the drafts folder, but for some reason I can’t get around to finishing them. With this post, I’d like to reactivate blogging around a more niche subject: Standard ML and its modern offshoot: SML#.

The Book

cover of #で始める実践MLプログラミング

Let’s get right into it. I’m not going to go into details about SML# or how it came to be, as that information is available on the project’s website. Instead, I’m going to take advantage of the fact that I happen to still remember how to read Japanese, and convey the gist of each chapter of the book to the English-speaking programmer.

Some info about the book: The Japanese title roughly means: “Starting Practical ML Programming with SML#”, but the back-cover gives the following English translation: “Practical Programming with SML#”.

The book has two authors: Atsushi Ohori (大堀淳) and Katsuhiro Ueno (上野雄大), both academics, both involved in teaching and developing Standard ML, and subsequently the main designers and creators of SML#. The book was published in Japan in 2021 by Kyoritsu Publishing.

Who Is This Book For?

After reading the first chapter, I’m leaning towards the opinion that this is a book for someone who is somewhat familiar with programming in a hobbyist capacity. Perhaps a high-schooler or first-year Computer Science student.

First Impressions of Chapter 1

Chapter 1 is titled “Setting up an SML# Programming Environment”, and as these kinds of chapters tend to do, tries to strike a balance between telling you exactly how to get a working SML# environment, but not holding your hand to an extreme degree. It gives only general instructions for both virtualbox and source-based installation. Once that’s overwith, and smlsharp is installed, the chapter packs a ton of content in a few short pages.

First of all, it showcases how modularity and partial builds are achieved in SML#, by separating out interface files (*.smi) from implementation files (*.sml). The authors put a nice twist on the old "Hello, world!" trope by having us define the string in question in one object file, and perform the acutal printing in a separate file, called main, and referred to as the command file.

Secondly: Unlike Standard ML, SML# supports international input, and the authors casually take advantage of this capability from the very outset, by defining the string to be "初めてのSML#プログラム". This is something the non-ASCII-users among us will definitely appreciate. I really loved this understated flex.

Thirdly, the authors demo how elegantly SML#’s partial build facilities integrate with standard POSIX Make. And before they do so, they motivate their work by saying:

During the development of large-scale systems spread across mutliple source files, there arise complex dependencies between the files, turning step 3 [dependecy resolution and recompilation] into a laborious manual process.

(p. 10)

While the statement above might come off as trivial to an old UNIX graybeard, I think that new programmers can certainly benefit from a reiteration of the fundamentals.


Before doing the exercises, I closed the book and tried to recreate the contents of chapter 1 from memory. I think this is called the Ben Franklin method – close the book and try to restate what you just read.

After doing so, I took a look at the exercises and indeed all four were about simply getting your hands dirty with the material presented in the chapter.

Closing thoughts

I think that the best programming books are those written by the creators of the programming technology in question. This seems to be the case for C (K&R), Lua (Programming in Lua), Erlang (Programming Erlang), Scheme (SICP), etc.

This book definitely fits that mold. The authors’ own summary of the work states that they are “experienced ML programmers and ML lovers”. Their love for the subject matter absolutely shines through, and the prose is very crisp and to-the-point.

I really enjoyed the first chapter and I’m looking forward to the rest!

My Answers to Exercises (SPOILERS)

(* Makefile *)

all0: all Makefile.smlsharp

Makefile.smlsharp: $(shell find . | grep '.sml$$\|.smi$$')
	smlsharp -MMm main.smi > $@

include Makefile.smlsharp

This Makefile lets me simply run make and ensure that the smlsharp-generated Makefile is recreated afresh when needed. It may be inefficient for larger projects, but for now I think it serves its purpose.

(* first.smi *)
val s : string;
(* first.sml *)
val s = "こんにちは、世界!\n";
(* main.smi *)
_require "basis.smi";
_require "./first.smi";
(* main.sml *)
print s;
Previous    |   Up   |    Next