型システムのしくみを先程読み終わった。

個人的にはこういうコンセプトの本は好きなので応援したい所だが、 思ったよりもいまいちな本だった、と言わざるをえない。 そしてそれは結構意外な事だったので、ブログにしておく意義もあるだろう、という事でブログにしておく。

読む前の自分の背景知識

自分は型システムをFolangMFGで2回ほどまぁまぁちゃんと実装している。 これ以外にもおもちゃとして実装した事はある。 基本的な実装がどうなるか、とか、どういう所が意外と苦戦するのか、 とかには一定の経験がある。

知識的には虎本の型のあたりはひととおり読んで、いわゆるAlgorithm-Wを実装した事はある。 型理論のようなものは素人で型システム入門(いわゆるTAPL)は読んでいない。 たまに単発の論文(それこそAlgorithm-Wの論文とか)を実装の参考にする目的で読む事はあるが、 理論的な事は素人の範疇だろう。 言語処理系の定番教科書に出てくる型のあたりはちゃんと理解して実装も結構しているので、 実装はそれなりに詳しい方だと思う。

後半3つの記事は割と良い

そんな自分にとっては、7章の部分型、8章の再帰型、9章のジェネリクスは割と良かった。 この3つが単発記事としてあったり、みっつで1000円くらいの同人誌的なものとして売っていたら、 割と高評価だったと思う。

前半部分は出来が悪い

だが1章〜6章(前半部分と呼ぶ事にする)は酷い出来で、一冊の本としてはいまいちだった、と思う。

1章〜6章は、めちゃくちゃ素人向けに進む。プログラムもめちゃちょっとずつ提示していき、 頭を使わずに読むだけで分かるように書かれている。 初心者向けなのは自分にとってはいまいちだがまぁいい。 だが内容が初心者向けだとするといろいろいまいちなのがこの本を評価出来ない所だ。

自分の言語に型をつけるのにも、既存の言語に型をつけるのにも使えない

この本がいまいちと思う所の一つに、TypeScriptという特殊性のためにスキップできる基礎的な話題はすべてスキップするのに、 TypeScriptという特殊性のために必須になる事も全部スキップする、という所にある。

たとえば自分の言語に型をつける場合には、言語設計と型がからむ所の話題が欲しいが、そういうのが無い。 たとえば数値のリテラルをどういう型として扱うべきか、という話題が全く無い。 C言語とKotlinやSwiftみたいな最近の言語が大きく異なる所だが、 どうして異なるのか、という話が全くない。それは言語設計に型システムが影響を与える所なので、 自分の言語を作ろうとするなら知っておくべき基本的な話になる。 けれどTypeScriptは言語自体を設計せずに既存の言語につける、というものなので、 この手の言語設計の話題が一切無い。 だから良くあるコンパイラの授業とかのように、 電卓に関数とレコードを足したくらいの言語に型をつける、みたいな入門者的な使い方にも不足がある。

けれど既存の言語にちょっとずつ型をつけよう、という問題を考えた時には、 言語側をいじれないが故にどういう問題があるのか、みたいな話が欲しい所だけれど、 そういうものも一切あつかわない。 端的に言えばとりあえずanyで既存の言語を全て通すところから始めて、 チェック出来る所だけを追加していく、的な構成になっていないので、 既存言語という既に出来ていて複雑で型の事を考えていない所に型を足す入門にもなっていない。 ランタイムに一切残さない結果どういう事が実現出来ないのか、という話もない。

そのくせに入門のtoy言語の割には関数定義がアロー関数とfunctionがある。なんでやねん。一つでいいやろ。

入門の題材としてTypeScriptを変に曲げたものはいまいちだな、というのが最後まで読んだ印象。 これなら良くあるコンパイラの入門書のように、電卓に変数とレコードと関数つけたくらいに型をつけた方が、 少なくともどういう世界に型をつけられたのか、は分かるので、そこから積み重ねる事ができそうなんだが。 この本のサブセットは最終的にどういう閉じた形態になっているのかが良く分からないので、 何が通って何が通らないのかが良く分からない。おもちゃとして微妙。

TypeScriptへの敬意をまったく感じない

この本が思った以上に好きになれない所として、TypeScriptへの敬意をまったく感じないという所がある。 TypeScript的な部分を、凄く雑に無視した選択をしては、 理由が「TAPLがそうだから」という、なんの理由にもなってない理由だったりする。 まるでML系の言語で書くかのような変な再帰構造とか、 TypeScriptという言語への愛をまったく感じない。

TypeScriptは凄く特殊な言語なのだが、その特殊性への言及があまり無くて、 本書を読んでもTypeScript的な事は全然わからない。 サブセットを実装するのはいいのだが、 根幹にかかわる所を削る場合はそこへの言及が欲しい。 でもそういうのは無く、なぜかTAPLを削るところへの言及はいろいろある。 いやいや、TypeScriptの話してよ、TypeScriptのサブセットを実装するって本なんだから、 と思ってしまう。 たとえば最後までthisへの言及はまったく無い。 TDZも言葉すらでてこない。 こういうのは全部理解した人に配慮した上で扱わない、というのはいいと思うのだが、 そういうめくばせを何も感じない。 最近読んでたTypeScriptHandbookはそういうのを全てわかった上で結論だけを語り間の理屈を全部カットする事で、 初心者向けの記述でありながらそうした事を全部分かっている人にもまったく分からない部分がない、という内容になっていたのとは正反対だ。

サブセットの切り方がTypeScriptから枝葉の機能を削ったもの、という感じになってなくて、 全然別の言語の定番の機能セットがベースになってるみたいに感じられる。 けれどTypeScriptゆえにそこから幾つか削れる所を削ってしまっているので、 残ったものが何なのか良く分からない。 TypeScriptから枝葉を削ったものじゃないので、TypeScriptの基礎的な部分が深く理解出来る、という感じになってないんだよなぁ。 むしろTypeScriptはこうじゃないだろう、みたいな所ばかりで、読んでいて納得がいかない。

なんというか、本のコアの魂の所にTypeScriptが無い。 これには凄くがっかりした。

言語処理系の教科書の話題に沿っていない

入門者向けとしてはいまいち、と感じるのは、教科書的な話題をちゃんと消化していかない所にある。

コンパイラの教科書とかでは、それぞれのトピックごとに消化すべき話題がある。 これは教科書が変わってもだいたい同じで、 オンラインのOCWとかのコンパイラの授業でもだいたいこれに沿った内容になっている。

たとえばオブジェクト指向プログラムと言えば、 メソッドのhoistとかの話題が必ずある。 メソッドは自身の別のメソッドを呼びあうのが一般的なので、 これは言語設計とあわせてどうするのか、という話がある。

という事で本書のオブジェクトの所でもそういったものの型づけについてどう実現するのかな? と思って読んでいくと、そういう話がぜんぜん無い。

でも6章では再帰関数の話題が唐突に出てくる。letとletrecの話なら理解出来るが、 JavaScriptでそれは無いんじゃないか…と思ってしまうような実装になっている。

コンパイラの教科書に沿って型づけの話題をしていくのではなく、 章立てはほとんど同じなのに扱うべき話題を完全に無視して進む。 無視してもいいのだが、言及くらいはしてもいいんじゃないか、 と思うのだけど、TAPLへの言及ばかりで標準的なコンパイラの教科書で扱う話題について何をスキップしているかを示さない。

型システムの入門書としては、標準的な言語処理系の教科書のうち簡単な所だけを扱いつつ、 扱わなかった話題についてはより進んだ本を読みましょうね、となっていて欲しいのだが、 当然扱うと期待するような話題を何も言わずにスキップしたり、 そうかと思えば散発的に突然あとで扱ったりして、 何を飛ばしたのかが全然わからない。

理論の話も無い

典型的なコンパイラの教科書を無視して進むのだから、実装よりも理論だ、という感じの本なのか、 という気がするし、実際そちらによせている内容に見えるのだが、 けれど理論の話は一切無い。 これが不思議な所で、理論の入門書じゃないんだよなぁ、この本。

だから理論を学びたい人向けの入門書にもなっていない。 序盤の実装になれてない人向けの記述は、いかにもそういう人向けの本だと思うんだが…

実装の入門の本でも無いが理論の入門の本でもなく、 ではこれはなんなんだ?という良くわからない本になってしまっている。

言語処理系の実装経験の全然ない人にえんえんとTAPLの話をする謎

この本の前半は、言語処理系をまったく実装した事が無い人向けに書かれている。 たとえばスコープとかを一通り実装している人にとってはかえって読みにくい感じに話がすすむ。 それ自体は対象読者のレベルの話なので、善悪の問題ではなく選択の問題だと思う。

けれど、そういうレベルの人向けの解説になっているのに、何故かえんえんとTAPLの話する。 TAPLは型理論の教科書だと思うのだが、型理論というのは一部の専門家の学ぶ領域であって、 大多数の人は理論的な話は必要無い。 コンパイラの教科書などでも数学的な理論の証明などはおまけというか発展的な内容として触れる程度で、 プログラムの意味論などの教科書は普通はその後に読むものだ。 型システムだって普通に考えたらそうだろう。

でもこの本は実装の基本的な話を知らない段階の人向けに書かれているのに、 何故か数学的な理論の本への言及がえんえんとされている。なんで? それよりも前にコンパイラの教科書への言及が必要だと思うのだが、 それは無いどころか章立てや扱い内容が対応していないのでコンパイラの教科書の型の章の前に読むのに使いにくい。 実際この本の対象読者のレベルではこの本の後には虎本の型システムの所はまだ手強すぎて取り組めないだろう。 けれどそこをすっ飛ばしてTAPLの話をする。 明らかにこの本の次にTAPLなんて読んでも分からないと思うのだが。

なんというか、入門者と中級者の話題がまざっちゃってるくらいならいいのだが、 言語処理系の実装が素人な対象読者と型理論の教科書という両者は、もっとずっとかけはなれたもので、なんでその二つを混ぜようと思ったのだろう…状態。

TAPLの一つ前の本を作りたいのかもっとずっと初心者が型システムの雰囲気をちょっと味わう本を作りたいのかが良くわからないというか、どちらにもなれてないんだよなぁ。 経済学でもなんでも、入門書というのは普通は専門に進む前の、どこに進むにも必要となる基礎の所を教えて様々な応用への足がかりになるものだと思うのだが、 この本はそういう意味では型システムの入門書になっていない。 例えばMINIX本などのように、特定の実装を見ていきつつそれとは違う世の中の言語の型システムの違いを解説する、とか、そういう感じの本では無い。 世の中のいろいろな言語の型についての違いや共通点についての理解は深まらず、TypeScriptの型についての理解も深まらず、 普通の言語には発生しないTypeScriptという特殊な状況のうちTypeScriptに必要なものを抜いた謎の型システムにだけ少しだけ詳しくなる。 うーん、たぶんTAPLで扱っている型システムに近い何かだとは思うのだが、 なんで型理論なんてマイナー分野に突き進む事にしか使えないものにしてしまって、しかも対象読者を型理論に進む段階よりはるか前に設定してしまったんだろうか。

型システムの入門書なら、もうちょっと幅広い読み物的な話題が混ざっていて欲しいようにも思うのだが、そういうのは無い。 C言語でいろいろと生まれた型的な問題がどういうもので、後続の言語がどういう風にそれを改善したのかを読みもの的に説明する訳でも無く、 型推論から始まるHindley–Milnerの話なども全く出てこないので、この本のあとにどういう事を学んでいくのかの見取り図のようなものも得られない。 その代わりにTAPLへの言及を延々と繰り返す。なんで…

実装の経験を積まずに理論家を目指す、というのも、良くは無いにせよありえるかもしれないが、 それにしてはこの本は理論の入門も無いんだよなぁ。

なんでドラゴンブックとか虎本じゃなくてTAPLの話をしたんだろうか…

後半の難しさが、実装経験の必要性を示してしまっている

この本の後半は、前半の対象読者には理解出来ない感じになっている。 後半の方がずっと難しいのに、後半の方がずっと解説が少ない。 個人的には逆になっていて欲しい所だが、前半が初心者向けで後半が中級者向けになっていて、 その間にギャップがあるのはまぁそういう本もあるとは思う。

ただ、この後半の難しさというのは、型システムを理解するのにある程度実装経験が必要という事を示している部分があり、 それはこの本の前半の内容からTAPLには行けないという事をこの本自体が示してしまっているようにも思う。

例えばジェネリクスでは型と項のジェネリクスが出てきて、両者が凄く似ている。 けれど読む側はこれを頑張って意識的に区別して読まないといけない。 これは本書にもそう記述があって、不可避なものなので、書き方に問題がある訳では無い。 だが実際にある程度実装の経験が無いと、 この型の側のジェネリクスと項の側のジェネリクスの区別をするのは無理だろう。 だからやはりこの辺の理論的な話を進めていく前には、ある程度実装をして経験を積む必要がある。

それはつまり、この本の序盤の対象読者はいったんこの本を読んだら、自分なりに実装してみていろいろ経験を積む必要がある、 という事に思う。 ジェネリクスに限らず、この辺の話題はパース時のテキストのレベル、IRのレベル、ランタイムのレベルといろいろと似た構成要素が出てくるが区別しなくてはいけなくて、 型というのもそうした区別とかなり関わりの深い所になってしまう。 それらを区別してちゃんと理解するには、やはりそれらの実装経験は不可避なんじゃないか。

だからこのレベルの人に対して、実装への道筋を全く示さずに型理論の教科書への道筋を示す、というのは、やっぱり無理があるんじゃないかなぁ。

総評: いまいちな本だったと言わざるをえない

トピック的にも面白いと思うしイマドキの言語での実装で読みやすくて良い本になりうると思うのだが… やはり最後まで読んだ結果はいまいちな本だったと言わざるをえない。

これなら虎本の型の所の方がずっと応用しやすい。 あれをもう少し初心者向けにした入門書とかなら良かったと思うのだが、 なんでTAPLにいちいち揃えようとして変に使いづらくしつつ、ターゲットの読者はTAPLよりもはるか手前の全然関係ない人にしてしまったのかなぁ。

自分は後半だけなら割と良いと思えるが、前半の誰向けか謎なのに結構な長さになってしまっているのがくっついている結果、 どうしても本として良かったとは言えない。

何より言語処理系の本なのに対象言語への愛を感じないのが自分には致命的だった。 もう少し好きで書いてくれている本を期待していたので、JavaScript愛もTypeScript愛もまったく感じない内容に、読んでいて嫌な気持ちになった。 最後3章が結構良かったので終盤は少し持ち直したが。