java - 違い - 未定義 意味
Haskellで未定義とJavaでnullの違いは何ですか? (2)
Haskellで未定義とJavaでnullの違いは何ですか?
さて、少しバックアップしましょう。
Haskellの "undefined"は "bottom"値の例です(⊥と表示されます)。 このような値は、プログラム内の未定義、固着または部分的な状態を表します。
終わりのないループ、例外、パターンマッチの失敗 - 基本的にはプログラム内の何らかの意味では定義されていない状態です。 値undefined :: a
は、プログラムを未定義の状態にする値の標準的な例です。
undefined
れていないものは特別なものではありません。それは有線ではありません。そして、下界の式を使ってHaskellのundefined
を実装することができます。 例えばこれはundefined
有効な実装です:
> undefined = undefined
またはすぐに終了します(古いGoferコンパイラはこの定義を使用していました)。
> undefined | False = undefined
ボトムの主な特性は、式がボトムに評価されると、プログラム全体が最下位と評価されます。プログラムは未定義の状態です。
なぜあなたはそのような価値を望んでいますか? 怠け者の言葉で言えば、ボトム値を格納する構造体や関数を操作することができます。
例えば、無限ループのリストは完全にクロムとなります:
> let xs = [ let f = f in f
, let g n = g (n+1) in g 0
]
> :t xs
xs :: [t]
> length xs
2
私はリストの要素をあまり使うことができません:
> head xs
^CInterrupted.
無限のもののこの操作は、なぜHaskellがとても楽しく表現力豊かなのかの一部です。 怠惰の結果として、ハスケルは特にbottom
値に細心の注意を払う。
しかし、明らかに、bottomという概念は、Javaやその他の言語にも等しく適用されます。 Javaでは、「ボトム」値をもたらす多くの式があります。
- ヌルに対する参照を比較する(ただし、
null
ではないが、それは明確に定義されている)。 - ゼロによる除算。
- 範囲外の例外。
- 無限ループなど
あなたはちょうど別のものを別のものに簡単に置き換えることはできませんし、Javaコンパイラはボトム値を理由づけて多くのことをしません。 しかし、そのような価値が存在します。
要約すれば、
- Javaで
null
値を逆参照することは、Javaでボトム値を生成する1つの特定の式です。 - Haskellで
undefined
れていundefined
値は、底値がHaskellで必要とされるどこでも使用できる一般的な底産出式です。
それは彼らが似ている方法です。
ポストスクリプト
null
自体の問題については、なぜそれが悪い形であると考えられるのですか?
- まず、Javaの
null
は、本質的に、Haskellのすべての型a
に暗黙のMaybe a
を追加することと等価です。 - Dereferencing
null
は、Just
場合のみのパターンマッチングに相当しnull
f (Just a) = ... a ...
したがって、渡された値がNothing
(Haskellの場合)またはnull
(Javaの場合)の場合、プログラムは未定義状態になります。 これは悪いです:プログラムがクラッシュします。
したがって、 すべての型にnull
を追加することで、偶然、 bottom
値を作成するのがずっと簡単になりました。 あなたの言語はもはやそのような特定の種類のエラーを防ぐのを助けるものではなく、それは悪いことです。
もちろん、他のボトム値、つまりundefined
ような例外、または無限ループが存在します。 新たな可能性のある障害モードをすべての関数に追加すると、 null
間接的に参照するだけで、クラッシュするプログラムを簡単に書くことができます。
どちらもタイプがすべてのタイプの交差点(無人)である用語です。 両方を評価しようとするまで、コードを渡すことができます。 私が見ることのできる唯一の違いは、Javaでは、参照平等比較( ==
)である1つの操作に対してnull
を評価できる抜け穴があることです。ハスケルではundefined
をスローせずに評価することは全くできません例外。 これは唯一の違いですか?
編集
私が実際にこの問題を解決しようとしているのは、Javaにnull
を含めるのはどうやら貧弱な決定だったのか、そしてHaskellはそれをどのようにエスケープするのでしょうか? 実際の問題は、あなたがnull
で役に立つ何かをすることができる、つまりヌルネスをチェックできるということです。 あなたがこれを行うことが許可されているので、コード内でヌル値を渡し、「このプログラムに論理エラーがあります」ではなく「結果がありません」と表示するのが標準的な慣習になりました。 ハスケルでは、用語が評価されずに評価され、プログラムが爆発的に評価されるかどうかをチェックする方法はないため、「結果がない」というような方法で決して使用することはできません。 代わりに、 Maybe
ようなものを使用するように強制されます。
申し訳ありませんが、私は速く遊んでおり、 "評価"という用語で緩んでいます...私はここで類推を引き出し、問題を正確に表現しようとしています。 私はそれが類推が不正確であるという兆候だと思います。
あなたの説明はあまり正確ではありません。 null
は評価できないと言っていnull
。 しかし、javaは熱心な言語なので、 f
の定義が何であっても(メソッドの引数は常にメソッドが実行される前に評価されるためf(null)
、 f(null)
はNPEをスローすることになります。
例外を取らずにhaskellでundefined
を渡すことができる唯一の理由は、haskellが怠惰であり、必要でない限り引数を評価しないということです。
undefinedとnullのもう一つの違いは、 undefined
は標準ライブラリで定義されている単純な値であるということです。 標準ライブラリで定義されていない場合は、自分で定義することができます( myUndefined = error "My Undefined
など)。
Javaではnull
はキーワードです。 null
キーワードがなければ、それを定義することはできません(haskell定義に相当するもの、つまりObject myNull = throw(new Exception())
、式が正しく評価されるために機能しません) 。