50

side effectのウィキペディアのエントリによると、例外の発生は副作用を構成します。この単純な python 関数を考えてみましょう:

def foo(arg):
    if not arg:
        raise ValueError('arg cannot be None')
    else:
        return 10

で呼び出すと、foo(None)常に例外が発生します。同じインプット、同じアウトプット。参照透過です。なぜこれは純粋な関数ではないのですか?

4

5 に答える 5

35

純粋性は、例外を観察し、それに基づいて制御フローを変更する決定を下した場合にのみ違反されます。実際に例外値をスローすることは、参照透過的です。これは、非終了またはその他のいわゆるボトム値と意味的に同等です。

(純粋な) 関数がtotalでない場合、それは底値に評価されます。一番下の値をどのようにエンコードするかは実装次第です - それは例外かもしれません。または非終了、またはゼロによる除算、またはその他の障害。

純関数を考えてみましょう:

 f :: Int -> Int
 f 0 = 1
 f 1 = 2

これは、すべての入力に対して定義されているわけではありません。一部の場合、それは底に評価されます。実装は、例外をスローすることによってこれをエンコードします。MaybeorOption型を使用するのと意味的に同等である必要があります。

現在、参照の透明性を破るのは、底値を観察し、それに基づいて決定を下す場合のみです。これにより、多くの異なる例外がスローされる可能性があり、どれがどれかわからないため、非決定論が導入される可能性があります。このため、例外のキャッチはIOHaskell のモナドにありますが、いわゆる「不正確な」例外の生成は純粋に行うことができます。

したがって、例外を発生させること自体が副作用であるというのは正しくありません。例外的な値に基づいて純粋な関数の動作を変更できるかどうか、つまり参照透過性を壊すことができるかどうかが問題です。

于 2012-05-23T12:35:27.353 に答える
16

最初の行から:

「コンピューター サイエンスでは、関数または式は、値を返すだけでなく、状態を変更したり、呼び出し元の関数や外界との観察可能な相互作用を行ったりする場合、副作用があると言われています。」

それが変更する状態は、プログラムの終了です。なぜそれが純粋な関数ではないのかについてのあなたの他の質問に答えるために。例外をスローするとプログラムが終了するため、関数は純粋ではありません。したがって、副作用があります (プログラムが終了します)。

于 2012-05-22T13:43:39.680 に答える
6

参照透過性は、計算 (関数呼び出しなど) を計算自体の結果に置き換える可能性でもあります。これは、関数が例外を発生させた場合には実行できないことです。これは、例外が計算の一部ではなく、キャッチする必要があるためです。

于 2012-05-22T13:43:55.103 に答える
4

例外の発生は、純粋または非純粋のいずれかであり、発生する例外のタイプに依存します。経験則として、例外がコードによって発生した場合は純粋ですが、ハードウェアによって発生した場合は通常、非純粋として分類する必要があります。

これは、ハードウェアによって例外が発生したときに何が起こるかを見るとわかります。最初に割り込み信号が発生し、次に割り込みハンドラーが実行を開始します。ここでの問題は、割り込みハンドラーが関数の引数でも関数内で指定されたものでもなく、グローバル変数であったことです。グローバル変数 (別名状態) が読み取られたり書き込まれたりするたびに、純粋な関数はなくなります。

これを、コードで発生する例外と比較してください。既知のローカル スコープの引数または定数のセットから Exception 値を作成し、結果を「スロー」します。グローバル変数は使用されていません。例外をスローするプロセスは、基本的に言語によって提供される構文糖衣であり、非決定論的または非純粋な動作を導入しません。Donが言ったように、「MaybeまたはOptionタイプを使用するのと意味的に同等である必要があります」。つまり、純度を含むすべての同じプロパティも持つ必要があります。

ハードウェア例外の発生は「通常」副作用として分類されると言ったとき、必ずしもそうである必要はありません。たとえば、コードが実行されているコンピューターが例外を発生させたときに割り込みを呼び出さず、代わりに特別な値をスタックにプッシュする場合、それは非純粋として分類できません。IEEE 浮動小数点 NAN エラーは、割り込みではなく特別な値を使用してスローされるため、浮動小数点演算の実行中に発生した例外は、値がグローバル状態から読み取られないため、副作用のないものとして分類できますが、 FPU にエンコードされた定数。

ピースコードが純粋で、コードベースの例外であり、ステートメントのシンタックスシュガーをスローするためのすべての要件を見ると、すべてのボックスにチェックマークが付けられ、状態を変更せず、呼び出し関数または呼び出し以外のものと相互作用しません。それらは参照透過的ですが、コンパイラがコードを処理した後でのみです。

すべての純粋な対非純粋な議論と同様に、実行時間やメモリ操作の概念を除外し、純粋に実装できる関数は実際の実装に関係なく純粋に実装されるという仮定の下で操作しました。また、IEEE 浮動小数点 NAN 例外の主張の証拠もありません。

于 2016-05-12T06:34:39.447 に答える