Equality type (SML と OCaml の比較) [OCaml]
ML for the Working Programmer を読んでいたら equality type という概念が出てきた(定訳不明)。多相型より範囲の狭い概念で、等値であるかどうかの比較ができる型のことを指すらしい。等値であるかどうかの比較ができない型というのは例えば関数である。
SML では演算子「=」は2つの equality type をとる関数ということになる。SML/NJで「=」演算子の型を表示すると以下のようになる。
- op= ; stdIn:5.20-7.5 Warning: calling polyEqual val it = fn : ''a * ''a -> bool
警告の意味はよくわからない(ML for ~の例では出ていない)が、引数の型が ''a というものだということが分かる。普通の多相型はプライムがひとつの 'a などなのでそれとは型が区別されているということだ。
「=」演算子で関数の比較をするとエラーになる。
- fun f x = x + 1; val f = fn : int -> int - fun g x = x - 1; val g = fn : int -> int - f = g; stdIn:1.1-15.4 Error: operator and operand don't agree [equality type required] operator domain: ''Z * ''Z operand: (int -> int) * (int -> int) in expression: f = g
さて OCaml ではこれに該当する概念はあるのだろうか。まずは「=」演算子の型を表示してみる。
# (=);; - : 'a -> 'a -> bool = <fun>
OCaml では「=」演算子の引数は単なる多相型で、SML のような型の制限がないことがわかる。それでも SML と同様に関数の比較をするとエラーになる。
# let f x = x + 1;; val f : int -> int = <fun> # let g x = x - 1;; val g : int -> int = <fun> # f = g;; Exception: Invalid_argument "equal: functional value".
上記の例だと SML でも OCaml でもエラーが出るということに変わりはないように見えるが、SML のエラーはコンパイル時チェックによるエラーで、OCaml のエラーは実行時の例外である。以下のように実行されない条件節の中に関数比較を置いてみると分かる。
SML の場合:
- if true then true else f = g; stdIn:15.24-15.29 Error: operator and operand don't agree [equality type require d] operator domain: ''Z * ''Z operand: (int -> int) * (int -> int) in expression: f = g
OCaml の場合:
# if true then true else f = g;; - : bool = true
だから equality type についていうと OCaml より SML のほうが不正をコンパイル時に検出できる分だけ堅いということが言えるかもしれない。
[追記] 書いた後で「ふつうの Haskell」に同じような話題があったのを思い出した。Haskell では「型クラス」という概念があって制約付きの多相型を定義できるらしい。その中で equality type に相当するのは「Eq クラスのインスタンスであるような型(Eq クラスの制約を満たす型)」、ということみたいだ。(p.237~)
コメント 0