このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

続・Erlangの型記法(間違い訂正)

「Erlangの型記法(Type Notation)」において、関数の型仕様(type spec)記述に関して、僕が誤解していた点があるので訂正します。間違っていたところは、次のような書き方の解釈です。


find_char(Str, Ch) -> integer()
Str = string()
Ch = char()
僕は、イコール記号の使用を慣例的濫用<らんよう>だと思っていました。そうじゃなかったんですよ。

誤解の背景

まず、僕の間違った解釈の背景を説明しましょう。

僕は、「Erlangの型仕様記述は、Cの関数プロトタイプ宣言と同じだろう」と理解しました。


/* C */
int find_char(string str, char ch);

% Erlang
find_char(Str::string(), Ch::char()) -> integer()

ねっ、同じでしょう。もっとも、Erlangの型仕様は言語に含まれるものではなくて、単なる規約ですけどね。

さて、昔(K & R)のCでは、関数ヘッダを次のように書きました。


int find_char(str, ch)
string str;
char ch;
この書き方をErlangに適用すると、

find_char(Str, Ch) -> integer()
Str :: string()
Ch :: char()
なんらかの理由で「::」が「=」にすり替わってしまうと、

find_char(Str, Ch) -> integer()
Str = string()
Ch = char()
これが、今使われている記法だな、っと。←間違い!

イコールは型変数への代入

上記の解釈が勘違いであることは、EDocのマニュアル(http://www.erlang.org/doc/pdf/edoc.pdf)の"1.1.13 Type specifications"を見て気が付きました。

find_char(Str, Ch) のStrやChは引数変数ではなかったのです。StrやChは型変数(type variable)であり、型表現の代理として置かれています。つまり、Str = string() と Ch = char() を一種の代入文だと思って、find_char(Str, Ch) は、find_char(string(), char()) と具体化して解釈すればいいのです。実に単純だね。

型変数を使うのは、型表現が複雑でうっとうしくなるときや、説明的な型名を使いたいときです。型表現を書ける場所なら、どこにでも型変数を書いてかまいません。そして、型変数の具体化を、イコール記号を使った代入文もどきで行うわけです。

引数変数と型変数の両方を使うこともできます。


find_char(S::Str, C::Ch) -> Index
Str = string()
Ch = char()
Index = integer()
型変数を説明的名前にしておけば、引数変数を付ける必要はあまりないでしょう。が、次の例では引数変数が“引数の役割”を示唆しています。

find_substr(Sub::Str, Total::Str) -> Index
Str = string()
Index = integer()

意外と整合的な型システム

Erlangの型記法(type notation)は、言語仕様の外にある規約に過ぎません。しかし、型変数や型構成子が自由に使えるとなると、形式的に割ときれいな型システムを作れそうです。面白いからやってみようと思いますが、それは別エントリーにします。