多値関数(2)

[id:m-hiyama:20060210:1139532309]で、多値がなければ成立しない例が知りたいということなので、Concurrent Cleanの例を説明しておきましょう。
CleanはHaskellに似た純粋関数型言語で、非正格な評価戦略をとっているため、実行順序がコードの文面とは異なる可能性があります。そのため、特に入出力など評価順序が重要になるケースでは、特別な対応が必要になります。
Haskellでは、これをモナドで取り扱いますが、Cleanでは、一意型属性という特殊な属性を型に与えて、入出力などに関わる関数には、一意型のオブジェクトを受け渡すことで、その評価順序を保証しています。
http://sky.zero.ad.jp/~zaa54437/programming/clean/LanguageReport21/Chap9.html
基本的な考え方は、以下のように前の関数の返値を次の関数に渡すことで、関数と関数の順序付けを表現することです。そして、順序付けに使われるオブジェクトが、必ず正しく順序付けを表現することを保証するために、一意型属性という機構を言語が提供しています。

u1 = f0 u0
u2 = f1 u1
u3 = f2 u2
...
u<n+1> = f<n> u<n>

このように、一意型を使った入出力関数では、関数の引数の1つと返値の1つが、必ず順序付けのためのオブジェクトで占有されてしまうため、それ以外の値を返値として返す関数(典型的な例が、ファイル読み込み関数)は、必ず複数の値を返すことになります。(以下、ファイル入出力関数の例)

(file, filesystem) = stdio filesystem // 標準入出力を開く
(ok, filesystem) = fclose file filesystem // ファイルを閉じる
file = fwrites text file // ファイルにテキストを書き出し
(line, file) = freadline file // ファイルから一行を読み込み
(is_end, file) = fend file // ファイルの終端かどうかを確認

このようなケースでは、関数が多値を返せることが、言語の成立の必須要件になります。