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

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

スキーマ構文の変更案(ラフ)

他の構文との整合性がなくなってきたとかの理由で、スキーマ構文を変更の予定。

将来的には型関数(型変数を持つ型構築子、総称型)も認める方針として、現状では型演算子を多用することにする。

構文構成素

  1. 型定数:意味が定まった型の名前。string, null, anyなど。
  2. 型変数:未定な型を意味する。
  3. 型関数:型変数を含む型表現、型を受け取り型を返す関数(多くの場合、関手の対象部分)を意味する。
  4. 演算子:型関数と同じだが、特殊な構文。

型定数

  1. integer
  2. number
  3. string
  4. boolean
  5. null
  6. array (新規)
  7. object (新規)
  8. never
  9. any

演算子

  1. '?' オプショナル演算子(単項後置)
  2. '|' 排他的ユニオン演算子(2項中置)
  3. '&' インターセクション演算子(2項中置)
  4. '*' クリーニスター演算子(単項後置)
  5. '[', ']' 配列生成演算子(n項前後置)
  6. '{', '}' オブジェクト生成演算子(n項前後置)
  7. '@' タギング演算子(2項前置)
  8. '(', ')' 属性付加演算子(2項特殊)

演算子の注意事項

  1. ユニオン演算子の被演算項は、複数のリテラル、または複数のタグ付き(暗黙タグ含む)型で、排他的でないといけない。
  2. クリーニスター演算子は、配列の内部、しかも最後でないと使えない。
  3. 属性付加演算子は、関数呼び出しと似た形式で型表現を修飾する。グルーピング用の丸括弧との区別は文脈で行う。

ラムダ式

「type<型変数の並び> 型表現」という形を型ラムダ式と呼ぶ。typeの直後の型変数は束縛変数になる。型定数と型変数に本質的な違いはないが、型定数はラムダ束縛(型抽象)が禁止されている変数である。

通常のラムダ計算と同じように型ラムダ計算が定義できる。

型代入

構文上は、「型の名前」は型定数と同じである。単に事前に定義されてない名前がユーザー定義型の名前として使える。定義されてない、つまりまだ意味が定まってない型の名前には、自由に型を代入してよい。

aが型の名前(まだ定義されてない)、Eが型表現なら、a = E は合法な型代入文である。特に、a = type<_X1, ..., _Xn>E; を type a<_X1, ..., _Xn> = E; とも書く。これによって、aという名前の型関数が定義できる。

型引数リストが空 <> のときは常に省略する。スキーマ属性による修飾(あれば)は型引数の直後に付ける。


type list<_T> = [_T*];
type listMax100<_T> = [_T*](maxItems = 100);
type pair<_X, _Y> = [_X, _Y];
type objPair<_X, _Y> = {"fst":_X, "snd":_Y};

array, objectはもはや型名で、次のように事前定義されている。


type array = [any*];
type object = {*: any}; // 厳密にはany?だが、?は省略可能というコンベンション

上記のlist型関数(型引数が1つ)は、使用頻度が高いので事前定義としてもいいだろう。従来と違うのは、角括弧が山形括弧に変わることだけ。

問題

  • このままでは、任意の高階型(通常の関数型(ベキ)を含めた高階型とは違う。型関数もまた型とみます高階型)が定義出来てしまうので制限しなくてはならない。
  • 構文解析が破綻しないか検討する必要がある。