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

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

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

参照用 記事

型推論に関わる論理の概念と用語 その4:JavaScript風の擬似言語

与えられた項(term)に型付け(typing)することは、型に関わる基本的行為ですが、なにかしら項の書き方(構文)を決めておかないと例を出せません。普通はラムダ項が使われるのですが、もっと馴染みがある構文を定義しておきましょう。以下で、項(term)と式(expression)は同じ意味で使います(使い分けの基準はありません)。

内容:

  1. ラムダ項をJavaScript風に書く
  2. let式
  3. 型let式

シリーズ目次:

  1. その1
  2. その2
  3. その3
  4. その4
  5. その5
  6. その6
  7. 番外(型理論ってば)

ラムダ項をJavaScript風に書く

ラムダ計算の説明にJavaScriptは好都合です(「JavaScriptで学ぶ・プログラマのためのラムダ計算」を参照)。λ(x, y).(x + y) を function (x, y){return (x + y);} と書けます。だけど、return がいかにも邪魔ですね(「returnも嫌いな理由」も参照)。returnは書かなくてもいいことにしましょう。つまり、function (x, y){x + y} でいい、と。これならもう、ほとんどラムダ項そのもの。

関数の引数と戻り値の型を次の形で宣言できるとします。

  • function (x:integer, y:integer):integer {x + y}

これは型付きラムダ項に対応します。ただし、型宣言は必須ではなくて、あってもなくてもいいとします。

引数変数だけでなく、どこに出現した変数にも型を添えていいとします。例えば、

  • function (x, y):integer {x:integer + y:integer}

出現位置のその場で型宣言をするようなものです。このような形での、変数への型情報付与を型注釈(type annotation)と言います。最初に出した、引数と戻り値の型宣言も型注釈とみなして差し支えありません。

let式

変数を束縛しておいてから式を評価することを表すためにlet式がよく使われます。次の形を使います。

  • let <変数束縛> in <式>

JavaScript風構文でもlet式を使っていいとします。

  • let {var x=2; var y=3} in {x + y}

この例では、x + y は 2 + 3 となり、全体の値は5です。すべての変数が束縛される必要はありません。

  • let {var x=2} in {x + y}

これだと、x + y が 2 + y になりますが、それ以上は評価できません。

  • let {var y=3} in {function (x) {x + y}}

これは、function (x) {x + 3} が値となります。

  • let {var x=2} in {(let {var y=3} in {function (x) {x + y}})(x)}

少し複雑ですが、注意深く順番に見ていけば、次と同じことがわかると思います。

  • (function (x) {x + 3})(2)

次はどうでしょうか? 考えてみてください。

  • let {var x=2} in {let {var y=3} in {let {var f = function (x) {x + y}} in {f(x)}}}

型let式

let式は、変数に値を束縛します。値には関数も含まれます(let {var f = function (x) {x + y}} がその例)。式の評価のための環境を整えていることになります。一方、式の型を知りたいときは、型付け(typing)の環境が必要です。それは、変数や関数の戻り値に型注釈を付けることになります。

型注釈を付けるための専用の構文、例えば lettype {var x:integer; var t:boolean} を導入してもいいのですが、めんどうだからletをそのまま使ってしまいましょう。

  • let {var x:integer; var t:boolean} in {function (y:integer) {if (t) {x} else {y}}}

function (y:integer) {if (t) {x} else {y}} だけだと、yの型しかわかりませんが、外側のletにおいて、x:integer; var t:boolean と型注釈(型宣言)されているので、x, y, tの型がハッキリとわかります。

let内では、変数の型注釈と値の束縛を一緒にやってもいいとします。

  • let {var x:integer=2; var t:boolean} in {function (y:integer) {if (t) {x} else {y}}}

if (t) {x} else {y} のような式だけだと、変数の型も値も不明です。let式によって、型情報や値情報を準備してあげることができます。すべての情報を明示的に与えなくても、与えられた情報をもとに計算や推論ができます。できるだけ少ない型注釈から、式やその部分式の型を決定することが、「型推論」のひとつの解釈です。