これにはいくつかのアプローチがあります。1 つだけ受け入れなければならないことは、ある時点で、純粋な表現を取り、環境と相互作用することによってそれらを不純にする魔法の不純な機械が存在するということです。この魔法の機械について質問してはいけません。
頭のてっぺんから考えることができる2つのアプローチがあります。私が忘れていた少なくとも 3 番目のものが存在します。
I/O ストリーム
最も理解しやすいアプローチは、ストリーミング I/O です。関数main
は 1 つの引数を取ります。それは、システムで発生したことのストリームです。これには、キーの押下、ファイル システム上のファイルなどが含まれます。このmain
関数は、システム上で発生させたいことのストリームという 1 つのことも返します。
ストリームはリストのようなものです。一度に 1 つの要素のみを作成でき、作成するとすぐに受信者が要素を受け取ります。純粋なプログラムは、そのようなストリームから読み取り、システムに何かをさせたいときに独自のストリームに追加します。
このすべてを機能させる接着剤は、プログラムの外にあり、「要求」ストリームから読み取り、「回答」ストリームにデータを入れる魔法のマシンです。あなたのプログラムは純粋ですが、この魔法のマシンはそうではありません。
出力ストリームは次のようになります。
[print('Hello, world! What is your name?'), input(), create_file('G:\testfile'), create_file('C:\testfile'), write_file(filehandle, 'John')]
対応する入力ストリームは次のようになります
['John', IOException('There is no drive G:, could not create file!'), filehandle]
input
アウトストリームのインストリームがインストリームにどのように'John'
表示されたかを確認してください。それが原則です。
モナディック I/O
モナディック I/O は Haskell が行っていることであり、非常にうまく機能します。これは、演算子を使用して I/O コマンドの巨大なツリーを構築し、それらを結合して、main
関数がこの巨大な式をプログラムの外部にある魔法のマシンに返し、コマンドを実行し、指示された操作を実行することを想像できます。この魔法の機械は純粋ではありませんが、表現を構築するプログラムは純粋です。
このコマンド ツリーが次のようになっていると想像してみてください。
main
|
+---- Cmd_Print('Hello, world! What is your name?')
+---- Cmd_WriteFile
|
+---- Cmd_Input
|
+---+ return validHandle(IOResult_attempt, IOResult_safe)
+ Cmd_StoreResult Cmd_CreateFile('G:\testfile') IOResult_attempt
+ Cmd_StoreResult Cmd_CreateFile('C:\testfile') IOResult_safe
最初に行うことは、挨拶を印刷することです。次に行うことは、ファイルを書きたいということです。ファイルに書き込むことができるようにするには、まず、ファイルに書き込むことになっているものを入力から読み取る必要があります。次に、書き込み先のファイルハンドルを持つことになっています。これはvalidHandle
、2 つの選択肢の有効なハンドルを返す関数から取得されます。このようにして、純粋でないコードのように見えるものと純粋なコードのように見えるものを混在させることができます。
この「説明」は、質問してはいけない魔法の機械について質問することに近いので、いくつかの知恵でこれを締めくくります。
実際のモナド I/O は、ここでの私の例とはかけ離れています。私の例は、モナド I/O が純粋さを損なうことなく「ボンネットの下」のように見える方法についての可能な説明の 1 つです。
純粋な I/O の操作方法を理解するために私の例を使用しないでください。ボンネットの下で何かがどのように機能するかは、それをどのように使用するかとはまったく異なります。人生で一度も車を見たことがなければ、車の設計図を読んでも良いドライバーにはなれません。
実際に物事を行う魔法の機械について質問するべきではないと私が言い続ける理由は、プログラマーが物事を学ぶとき、彼らはそれを理解しようとするために機械を突っ込みたがる傾向があるからです. 純粋な I/O の場合はお勧めしません。機械は、さまざまなバリアントの I/O の使用方法について何も教えてくれない場合があります。
これは、逆アセンブルされた JVM バイトコードを見て Java を学ばないことに似ています。
モナドI/O とストリームベースの I/O の使い方を学びましょう。これは素晴らしい体験であり、ツールベルトの下にさらに多くのツールがあることは常に良いことです。