Haskellについて読んだときはいつでも、IOが副作用を引き起こす可能性があることがわかりました。
しかし、それがどのように行われるのかわかりませんか?
あるレイジーシーケンスからファイルに書き込んでいて、別のレイジーシーケンスが同じファイルから読み取っているということですか?
それが唯一の可能性ですか、それとも根本的に深いものがありますか?
Haskellオプティマイザは、結果が同じである限り、純粋な関数の呼び出しを自由に操作できます。たとえば、同じ番号でsqrt
を100回呼び出していることがわかると、戻り値をキャッシュして1回だけ呼び出すことができます。その関数の結果を実際には使用しないことがわかった場合は、まったく呼び出さないように選択できます。
これらは、IOでは実行できません。 stdinから100回読み取る場合、オプティマイザが最初の読み取りをキャッシュし、その値をさらに99回再利用するのは望ましくありません。コンソールに書き込んで戻り値を破棄する場合(putStrLn
の戻り値は実際には気にしないため)、オプティマイザが関数呼び出しを完全に削除することは望ましくありません。
それが副作用の意味です-プログラマーの視点からではなく(プログラマーがこれらのことを行うことを明確に意図したものではなく)、オプティマイザーの視点からです。
最も単純な例:「Hello、world!」システムの状態を変更します。これは、コンソールに「Hello、world!」が表示され、以前はそうではなかったためです。端末から文字を取得できないため、状態を変更しただけでなく、元に戻すことは実際には不可能です!それは可能な最も深刻な副作用についてです。
問題は、副作用が何を意味するのかが少し不明確だということです。副作用のない純粋な関数では、関数は入力の直接的な結果であり、それ以外のものはありません。副作用のある関数では、関数は外界の状態に依存するか、その状態を変更します。したがって、square(x)
のような関数がある場合、それは純粋な関数です。一方、launch_the_missiles()
のような関数がある場合、それは非常に現実的な副作用があります(またはより平凡な例では、ページを印刷します)。
IOを実行すると、世界の状態が変化します。つまり、副作用です。
CSの副作用の定義を知らないようです。関数は、その関数の外部でシステムと観察可能な相互作用がある場合、副作用があります。したがって、出力は常に副作用であり、出力がどこに行っても、ハードドライブ、ネットワーク、コンソールの変化を観察できます。入力は、関数で発生する計算に影響を与え、外部システムに影響を与える可能性があるため、同様に副作用です。つまり、コンソールまたはソケットからの読み取りです。
副作用とは、IO操作のたびに、システムの状態が変更される可能性があることを意味します。Haskellは、純粋なHaskellコードとIOコードを明確に分割します。
参照してください: http://learnyouahaskell.com/input-and-output#hello-world ;
本から:「Haskellでは、関数は変数の内容を変更するなど、一部の状態を変更できません(関数が状態を変更するとき、関数には副作用があると言います)。」
これを聞いたことがありますか 格言 ?
同じ川を2度踏むことはできません。再び、それは同じ川ではなく、彼は同じ人ではありません。
関数の1つが1
から/dev/ttyusb0
。 UNIXでは、これは「単なるファイル」ですが、実際には、これは実際にはマイクロコントローラの名前であり、1
パンスライス機を作動させ、500パンのパンパーニッケルをスライスします。 1
初めて500パンのパンパーニッケルが「スライスされていない」状態から「スライスされた」状態に移行しました。別の送信1
にはこの効果はありません(「スライス解除」に戻れないためです!)。それは同じ川ではありません。
別の関数がストリームからデータを読み取る場合を想像してください。それが静的ファイルである場合、おそらくそれを2回読み取って同じ結果を得ることができますが、代わりにストリームが(別の)マイクロコントローラー(これはベーキング温度を監視している)からのデータバッファーである場合、値を繰り返し読み取りますオーブンが加熱または冷却すると、再び異なる結果が得られます。彼は同じ人ではありません。