純粋関数型言語とそうでない言語の違い

某所の議論を見て思ったのだけれど、
普通のオブジェクト指向言語でプログラミングする時は、対象を内在化してプログラムを書くという手法が比較的多く採用されているような気がする。特に複雑な問題を定式化するときは、対象をオブジェクトの形で表現するというところから設計が開始する。UMLなんかはその線で進めることが前提になっている気がする。
対象を内在化してオブジェクトの関係を固定化すると、対象に対する操作は自然に副作用を伴う操作になる。そのため、そのようなアプローチで進めた設計は、純粋関数型言語とは相容れないものになってしまう。おそらく、普通のオブジェクト指向言語で育ったプログラマは、この壁にぶつかってなかなか乗り越えられないのではないかと思う。
純粋関数型言語を相手にするときは、対象を内在化してプログラムを書くという手法は全面的に捨てる必要がある。代わりに、対象を外在化するというアプローチが必要になる。
純粋関数型言語では、プログラムの「外」にある対象に対して破壊的な操作を行うために、言語の枠組の中にその手段が用意されている。そのため、対象を外在化することで、対象に対して自由に破壊的な操作を行うことができる。例えば、ファイルやネットワークや画面などは、外在化された対象の典型的な例だ。この対象には、メモリ領域も含めることができる。
このような外在化された対象にアクセスする方法として、Cleanは一意型という機構があり、HaskellにはIO Monadという機構があるが、いずれも外在化された対象がプログラムの内部に侵入できないように、仕掛けが施されている。そのため、このような言語でプログラムを書くためには、普通のオブジェクト指向言語でプログラムを書くときとは「外と内が逆転した」ような発想の転換が必要となる。
残念ながら私は、対象を外在化することを前提とした体系的な設計手法を知らないし、そういう設計手法が広く知られていないことは純粋関数型言語を使って一定以上の規模のプログラムを書くことを難しくしているのではないかと思う。もちろん、書ける人は書けるのだけれど。
なお、純粋関数型であることそのものは、速度やメモリ効率の面でのハンデにはつながらないのではないかと思う。実際、Cleanの速度やメモリ効率はとてもよい。Haskellのアレは処理系やライブラリの問題だと思う。

      • -

(追記)
はてぶコメントより

OOでも分厚いコントロール層を構築していくとメタファー的なプログラミングから離れていくよ。多態とか単一責務とか徹底すると結局は外在的になっていく。

「外/内」という概念は私自身の直感的な感覚を定義無しに使っているので伝わらないのは仕方ないですが、OO的にコントロール層を構築していくということこそ、対象を内へ内へと取り込んでいく手法です。よく「ラッピング」と言いますよね。対象をラップして抽象的な概念に再構成するというアプローチが、ここで内在的なアプローチと呼んでいるものです。