プロセスメモリからの読み取りを純粋な操作とするのは何ですか?グローバルメモリに100個の整数の配列を作成し、この配列の42番目の要素を取得したとします。副作用ではありませんよね?では、なぜファイルから100個の整数の同じ配列を読み取るのが副作用なのでしょうか?
プロセスメモリからの読み取りを純粋な操作とするのは何ですか?グローバルメモリに100個の整数の配列を作成し、この配列の42番目の要素を取得したとします。副作用ではありませんよね?では、なぜファイルから100個の整数の同じ配列を読み取るのが副作用なのでしょうか?
回答:
アクセスするメモリが変更される可能性がある場合、それは実際に副作用です。
たとえば、Haskellでは、可変配列(IOArray
)にアクセスする関数の型は
Ix i => IOArray i e -> i -> IO e
(私たちの目的のために少し簡略化されています)。不変配列にアクセスしている間は型があります
Ix i => Array i e -> i -> e
最初のバージョンIO e
は、I / O副作用があることを意味するタイプの何かを返します。2番目のバージョンは、e
副作用のないタイプの要素を単に返します。
ファイルにアクセスする場合、プログラムの実行中にファイルが変更されるかどうかをコンパイル時に知ることはできません。したがって、潜在的な副作用を伴う操作として常に扱う必要があります。
コンピューターサイエンスでは、関数または式は、値を返すことに加えて、状態を変更したり、呼び出し元の関数または外部世界と観察可能な相互作用がある場合、副作用があると言われています。 ファイルからの読み取りは、外界との観察可能な相互作用です。副作用の定義を満たします。グローバルメモリから42番目の要素を読み取ることは、配列が定数である場合を除き、副作用でもあります。これは、配列を変更する可能性のある他の関数との相互作用であるためです。
メモリからの読み取りは他の機能に影響を与えないため、副作用はありません。通常、ファイルから読み取ると、ファイルの位置ポインターが移動します。そのため、再度読み取ると、すでに読み取ったデータの後にデータが読み取られるため、1つの読み取り関数が他の読み取り関数の結果を変更します。これは副作用です。代わりに、この副作用が消えるよりも、一度にファイルを開いたり、読んだり閉じたりすると、大きなファイルには実行できません。さらに、ファイルを開く方法によっては、ファイルを開いた後にロックされる可能性があるため、最初のファイルを開いて読み取ろうとすると成功しますが、次の試行はファイルが既に開いていますエラーで失敗しますが、これも副作用です。
ファイルを一度に読み取り、同時に複数の読み取りを可能にする副作用のない読み取り関数を作成することは、読み取り関数の影響を受けるファイル書き込み関数があり、ファイル書き込み関数を取り除くことが再び不可能であるため、困難です。
IO
モナドを介してファイルのシーケンス変更操作を行うことができますか?)、読み取り用の副作用のない関数を作成できます。
などの関数の結果はisEOF
、読み取り後と読み取り前では異なる結果を返すことがあるため、ストリームからの読み取りはすでに副作用です。