このブログは、旧・はてなダイアリー「檜山正幸のキマイラ飼育記 メモ編」(http://d.hatena.ne.jp/m-hiyama-memo/)のデータを移行・保存したものであり、今後(2019年1月以降)更新の予定はありません。

今後の更新は、新しいブログ http://m-hiyama-memo.hatenablog.com/ で行います。

型解析:細かい注意点

never型、undefined、型変数の値となる領域

never型はいかなるインスタンスも持たない。never?型の唯一のインスタンスはundefinedと書く。undefinedは意味領域に存在する値だが、表層には出てこない。コマンドの入力にundefinedが入ることはなく、コマンドの出力にundefinedが混じることもあり得ない。undefinedはデータとして受け渡されるものではなく、配列の項目(item)、オブジェクトのプロパティ、タグ付き値のvalの不在の目印となるだけである。存在しない項目/プロパティ/valにアクセスした場合、undefinedが取り出せるわけではなく、例外などのエラーとなる。

型変数は、undefinedを含まない領域を表す。つまり、変数xに対して never⊆x は常に成立する(公理だ)が、never?⊆x は成立しない。変数がそのままでオプショナル型になることはなく、'?'を付けてはじめてオプショナル型になる。よって、T? ⊆ x は、Tが何であっても成立しない。

シングルトン型とnull

単にシングルトン型といえば、シングルトンスカラー型を指す。複合データを1つだけ含むシングルトン型は、シングルトンスカラー型と型構成子から作れる。

シングルトン型はスカラーリテラルによって表現される。つまり、

  1. 数値リテラルはシングルトン型
  2. 文字列リテラルはシングルトン型
  3. true, false, null はシングルトン型

となる。もともと、null値だけからなるシングルトン型がnull型だったので、nullはリテラルと型を同一視する方式に合致している。Catyでは、nullをシングルトンスカラー型として扱う。シングルトンではないスカラー型は、integer, number, string, booleanとなる。

暗黙タグを付与する方法

integer, number, string, boolean, null, array, object は型名として予約されている。arrayとobjectは次の定義を持つと考えてよい。

  • type array = [any*];
  • type array = {*:any?};

一方で、

  • any = (number|string|boolean|null|array|object)

なので、arrayとobjectの定義は再帰的になる(これは余談)。

  • type array = [(number|string|boolean|null|array|object)*];
  • type array = {*:(number|string|boolean|null|array|object)?};

integer, number, string, boolean, null, array, object のインスタンには、型名と同じタグを付けてよい。@integer 3, @number 3.14, @string "hello", @array [1, 2, 3] など。しかし、これらのタグはすぐに消滅してしまい、そのまま維持されることはない。

タグが付いてない値やデータに、どうしてもタグが必要な場合は、予約型名と同じタグ(暗黙タグ)を付与することができる。暗黙タグを付与する作業が必要になるのは、排他的ユニオンの排他性の検査のときだけである。特に、シングルトン型(スカラーリテラル)には次のルールでタグを付ける。

  1. 数値リテラルには、@number を付ける。このとき、@integerは使わない。
  2. 文字列リテラルには、@string を付ける。
  3. true, false には、@boolean を付ける。
  4. null には、@null を付ける。

排他的ユニオンの排他性のチェック

(T1 | ... | Tn) の形をしたユニオンが排他的である条件は:

  • すべての型のタグ(暗黙でもよい)が異なっていること。ただし、@integerと@numberは異なるとは認めない。

成分の型に明示的なタグが付いている必要はない。例えば、次の例は排他的となっている。


type coord = [number, number]
| {"x":number, "y":number}
| string(remark="座標のテキスト表現");

このcoord では (@array | @object | @string) という3つの暗黙タグが互いに異なる。

スキーマ構文では、次も許される。


type gender = ("male" | "female");

この例では、(@string | @string) となり、同じタグが含まれる。同じタグを持つシングルトン型をユニオンとして許すため、次の規則を入れる。

  1. ユニオンの成分に同じタグがあってもよい。
  2. ただし、同じタグを持つ型はシングルトン型に限り、それらは互いに排他的(異なる値)でなくてはならない。

シングルトン型またはスカラー型は、次のどれかのタグを持つ; @integer, @number, @string, @boolean, @null。これらのタグを持つ型の排他性は容易に判定できる。例えば、(1|integer), (2|2), (integer|number), (true|boolean) などは排他的ではない例。従来の列挙型、例えば (0|1|2) は、新しい排他性の定義から排他的となる。シングルトン型とスカラー型のあいだに明白な区別はないので、次のようなユニオン型も認める; (integer|false), (0|1|2|null), (number|"+inf"|"-inf")。

型変数が含まれるユニオンは排他性が保証されないので認めない。例えば、(_X|string), (@foo _X | @foo _Y) などは認めない。しかし、(@foo _X | @bar _Y) は排他的だとすぐわかるのでOK。

ユニオンの排他性は、一般の古典論理(∨を含む)を使わず、連言論理だけで型解析を済ませるために必要な条件である。古典論理の計算負担は、∨の多段枝分かれにより、ときに手に負えなくなる。連言論理の範囲内に収めることは効率上重要である。