モナドは、IOを処理するためのhaskellソリューションとして説明されています。純粋な関数型言語でIOを処理する他の方法があるかどうか疑問に思いました。
7 に答える
純粋な関数型言語でのI/Oのモナドに代わるものは何ですか?
私は文献の2つの選択肢を知っています:
1つはいわゆる線形型システムです。線形型の値は1回だけ使用する必要があるという考え方です。無視することはできず、2回使用することもできません。このアイデアを念頭に置いて、世界の状態に抽象型(たとえば
World
)を与え、それを線形にします。線形タイプに星印を付ける場合、いくつかのI/O操作のタイプは次のとおりです。getChar :: World* -> (Char, World*) putChar :: Char -> World* -> World*
等々。コンパイラーは、ワールドをコピーしないように調整します。次に、ワールドを適切に更新するコードをコンパイルするように調整します。これは、コピーが1つしかないため安全です。
Cleanという言語での一意性の入力は、線形性に基づいています。
このシステムにはいくつかの利点があります。特に、モナドが行うイベントの全体的な順序付けは強制されません。また
IO
、Haskellで見られる「罪のビン」を回避する傾向があります。この場合、すべての効果的な計算がモナドに投げ込まれ、IO
全順序が必要かどうかに関係なく、すべてが完全に順序付けられます。私が知っているもう1つのシステムは、モナドとクリーンよりも前のものであり、対話型プログラムは(おそらく無限の)一連の要求から(おそらく無限の)一連の応答までの関数であるという考えに基づいています。「ダイアログ」と呼ばれるこのシステムは、プログラミングするのにまったく地獄でした。誰もそれを見逃すことはなく、特にそれをお勧めすることは何もありませんでした。その欠点は、WadlerとPeytonJonesによるモナディックI/ O(命令型関数型プログラミング)を紹介した論文にうまく列挙されています。この論文はまた、エール・ハスケル・グループによって導入されたが短命であった継続に基づくI/Oシステムについても言及している。
線形タイプの他に、エフェクトシステムもあります。
Cleanでは一意性の型付けが使用されます
「純粋」とは「参照透過性」を意味する場合、つまり、適用された関数がその評価結果と自由に交換可能である場合(したがって、同じ引数で関数を呼び出すと毎回同じ結果が得られる)、ステートフルIOの概念定義上、ほとんど除外されています。
私が知っている2つの大まかな戦略があります:
関数にIOを実行させますが、まったく同じ引数で2回呼び出されないようにしてください。これは、関数を自明に「参照透過性」にすることで問題を回避します。
プログラム全体を単一の純粋関数として扱い、「すべての入力を受け取った」を引数として取り、「すべての出力を生成した」を返します。どちらも、対話性を可能にする何らかの形式の遅延ストリームで表されます。
両方のアプローチを実装するにはさまざまな方法があり、ある程度の重複もあります。たとえば、2番目のケースでは、I / Oストリームで動作する関数が、ストリームの同じ部分で2回呼び出される可能性はほとんどありません。それをどのように見るかがより理にかなっているのは、その言語がどのようなサポートを提供しているかによって異なります。
HaskellではIO
、コードを介してシーケンシャル状態を自動的にスレッド化するタイプのモナドであり(機能的に純粋なState
モナドと同様)、概念的には、そうでなければ不純な関数への各呼び出しは、外界の暗黙の「状態」の異なる値を取得します"。
私が知っている他の一般的なアプローチは、同様の目的で線形型のようなものを使用します。コピーまたは複製できない値を使用して、不純な関数が同じ引数を2回取得しないようにすることで、「外界の状態」の古い値を保持して再利用することができなくなります。
関数型IOに興味がある場合は、PeytonJonesとWadlerによる命令型関数型プログラミングを読む必要があります。彼らが議論する他のアプローチは次のとおりです。
- 応答と要求の怠惰な流れである対話
type Dialogue = [Response] -> [Request]
main :: Dialogue
継続-各IO操作は引数として継続を取ります
線形型-型システムは、外部状態をコピーまたは破棄できないように制限します。つまり、同じ状態で関数を2回呼び出すことはできません。
関数型リアクティブプログラミングは、これを処理するもう1つの方法です。
純粋な関数型言語でIOを処理する他の方法があるかどうか疑問に思いました。
すでにここにある他の答えに追加するだけです:
- この論文のタイトルはそれをすべて言います:-)
- また見ることができます:
Rebelsky SA(1992)I/Oツリーとインタラクティブな怠惰な関数型プログラミング。In:Bruynooghe M.、Wirsing M.(eds)プログラミング言語の実装と論理プログラミング。PLILP 1992.コンピュータサイエンスのレクチャーノート、vol631。Springer、Berlin、Heidelberg
- Haskellが若い頃、Lennart Augustssonは、I/Oのメカニズムとしてシステムトークンを使用することについて次のように書いています。
L.オーガストソン。システムトークンを使用した機能I/O。PMGメモ72、コンピュータサイエンス学部、チャルマース工科大学、S-412 96ヨーテボリ、1989年。
オンラインコピーはまだ見つけていませんが、差し迫った必要はありません。それ以外の場合は、Chalmersの図書館に連絡することをお勧めします。