Concurrent Clean : structural polymorphism

Cleanで次のようなプログラムを書いたとする。

Start = f {A|a=1}

::A = {a :: Int}
::B = {a :: Int, b :: Int}

f {a} = a

これは、fが多相的に機能してくれることを望んでいるのだけれど、残念ながら、{a}の型が曖昧なのでコンパイルエラーになる。
じゃあ、次のようにして、マクロ展開してしまえば、と思うが、やはりダメ。

f {a} :== a

思うに、これは、Cleanのコンパイラが{a}を見たときにこれだけからレコードの型を推論しようとするために起こることで、ならばレコードについてはフィールドの名前から型を推論しないようにすれば、マクロを使って多相レコード風に機能させることができるのではないかというアイデアを思い付いた。
レコードの型を、レコードのフィールド名を手がかりに推論するのを止めて、レコードの型は外的に必ず与える。ことになるけれど、これは許容できる負担ではないだろうか?(以下、この変更後に許容される例)

a = {A|a=1}
a :: A
a = {a=1}
f :: A -> Int
f {a} = a

i = f {a=1}
f {a} = a

i = f {A|a=1}

ちょっと余裕のあるときにコンパイラを修正して確かめてみよう。

      • -

[id:lethevert:20060831:p1] ← 関連している昔の記事