単一化で人間の気持ちが失われるんだ!というサビシイ話

OCaml 演習とかやってひぃひぃ言っている人対象ですぅ。わからない人にはわかるように書いていませんから、「さっぱりわからない」とか呟く前にスルー推奨です

type t = int list list list

let x : t = [[[1]]]
let y = x @ x

コンパイルすると、 x は t だが y の型は int list list list とレポートされる。これが残念だって話。だって明らかに t でしょ?
これはもちろん単一化アルゴリズムの気持ちになれば明らかに、明らかではないのだが…

それに、じゃあ x @ x の型が t としてレポートされるべきかというと、そうではないわな。

type kg = float
type m = float (* メーテル *)
let bmi (w : kg) (h : m) = w /. (h *. h)

としたときに bmi の戻り値が kg (もしくは m) になっていて欲しいですかあなたは?

あなたが単一化アルゴリズムの気持ちになれているかどうかは、

let z = [x] @ [x]

の型が int list list list list ではなく t list としてレポートできるのは何故か、で、なぜそれは bmi の例とちがっておかしさがないか、考えるといいですぅ。

どーしてもこれが嫌なら、

type t = Foo of int list list list

として別の型にせにゃならん、がもちろん (@) はそのままでは使えなくなる。

はっ!今気づいた。ようするに、あれだ。 (@) : 'a list -> 'a list -> 'a list は 'a は全部同じことを保証しているが、三つの 'a list が同じであることを保証していない。(いや、同じ型だよ、でも bmi の例と同じく、人間の気持ち的には同じ意味じゃないかもしれないよね?) だから、人間の気持ちを導入してやればよろしい:

let (@!) : ('a list as 'b) -> 'b -> 'b = (@)
let y = x @! x

はいできました。 y の型は t になるよ。

ようするに、機械の体は人間の気持ちを推論してくれないのだ。メーテル、サビシイね、と鉄郎は思った。