Haskellの未定義とJavaのNullの違いは何ですか?
質問
どちらもすべてのタイプの交差点(無人)の交差点である用語です。どちらも、それを評価しようとするまで、失敗することなくコードで渡すことができます。私が見ることができる唯一の違いは、Javaには、抜け穴があることです。 null
正確に1つの操作、つまり参照平等比較で評価される(==
) - haskellでは undefined
例外を投げることなく、まったく評価することはできません。これが唯一の違いですか?
編集
私がこの質問で本当にやろうとしているのは、なぜ含めることだったのかということです null
Javaでは、明らかに貧弱な決定であり、Haskellはどのようにそれを逃れますか?本当の問題はあなたが何かをすることができるということです 使える と null
, 、つまり、あなたはそれをチェックすることができます ヌルネス. 。これを行うことが許可されているため、コード内のnull値を渡し、「このプログラムには論理的なエラーがある」ではなく「結果がない」ことを示すことが標準的な慣習になりました。 Haskellでは、用語が評価せずに底部に評価され、プログラムが爆発するかどうかを確認する方法はありません。そのため、「結果なし」を示すために使用することはできません。代わりに、そのようなものを使用することを余儀なくされます Maybe
.
申し訳ありませんが、「評価」という用語で速くてゆるいプレーをしているように思われます...ここで類似性を描き、それを正確にフレージングするのに苦労しようとしています。それは類推が不正確であるという兆候だと思います。
解決
Haskellの未定義とJavaのNullの違いは何ですか?
わかりました、少しバックアップしましょう。
Haskellの「未定義」は、「底」値の例です(示されています)。このような値は、プログラム内の未定義、スタック、または部分的な状態を表します。
多くの異なる形式の底部が存在します:非終了ループ、例外、パターンマッチの障害 - 基本的に、何らかの意味で定義されていないプログラムのどの状態です。値 undefined :: a
プログラムを未定義の状態に置く値の標準的な例です。
undefined
それ自体は特に特別ではありません - 配線されていません - そしてあなたはhaskellの実装をすることができます undefined
ボトムイールド式を使用します。たとえば、これは有効な実装です undefined
:
> undefined = undefined
またはすぐに終了します(古いGoferコンパイラがこの定義を使用しました):
> undefined | False = undefined
底部の主な特性は、式が下部に評価された場合、プログラム全体が下部に評価されることです。プログラムは未定義の状態にあります。
なぜそのような価値が欲しいのですか?まあ、怠zyな言語では、プログラム自体が底にないことなく、底面の値を保存する構造または関数を操作することができます。
たとえば、無限のループのリストは完全にcrom式です:
> 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がとても楽しくて表情豊かな理由の一部です。怠lazの結果は、Haskellが特に細心の注意を払っていることです bottom
値。
ただし、明らかに、ボトムの概念は、Java、または任意の(非張力)言語にも同様に適用されます。 Javaには、「底」値を生成する多くの式があります。
- 参照をnullと比較する(注意しても、
null
それ自体、明確に定義されています); - ゼロによる分割;
- バウンド外の例外。
- 無限ループなど
ある底部を別のボトムに非常に簡単に置き換えることができないだけで、Javaコンパイラはボトム値について推論することはあまりありません。ただし、そのような値はあります。
要約すれば、
- 棄権a
null
Javaの値は、Javaの底値を生成する特定の式の1つです。 -
undefined
Haskellの値は、Haskellで必要な底部値が必要な場所で使用できる一般的な底式の式です。
それは彼らが似ている方法です。
ポストスクリプト
の質問について null
それ自体:なぜそれが悪い形と見なされるのですか?
- まず、Javaの
null
本質的に同等です 暗黙的な追加Maybe a
あらゆるタイプにa
Haskellで. - 解釈
null
のみのパターンマッチングに相当しますJust
場合:f (Just a) = ... a ...
したがって、渡された値がISです Nothing
(Haskell)、または null
(Java)、プログラムは未定義の状態に達します。これは悪いことです。プログラムがクラッシュします。
だから、追加することによって null
に 毎日 タイプ、あなたはちょうどそれを作成しやすくしました bottom
偶然の価値 - タイプはもはやあなたを助けません。あなたの言語はもはやあなたがその特定の種類のエラーを防ぐのに役立ちません、そしてそれは悪いことです。
もちろん、他の底部値はまだそこにあります:例外( undefined
)、または無限ループ。すべての関数に新しい可能な障害モードを追加する - 避難 null
- クラッシュするプログラムを簡単に作成できるようにします。
他のヒント
あなたの説明は正確ではありません。あなたは言っています null
評価することはできません。しかし、Javaは熱心な言語なので、これはそれを意味します f(null)
何の定義に関係なくNPEを投げる f
IS(メソッドの引数が常に実行される前に常に評価されるため)。
あなたが通り過ぎることができる唯一の理由 undefined
Haskellでは例外を得られないことは、Haskellは怠zyであり、必要でない限り議論を評価しないということです。
未定義とヌルのもう1つの違いはそれです undefined
標準ライブラリで定義されている単純な値です。標準ライブラリで定義されていない場合は、自分で定義できます(書くことによって myUndefined = error "My Undefined
例えば)。
Javaで null
キーワードです。いなかった場合 null
キーワード、あなたはそれを定義することができません(Haskell定義に相当する、つまり、つまり Object myNull = throw(new Exception())
, 、式がすぐそこに評価されるため、機能しません)。