HaskellのundefinedとJavaのnullの違いは何ですか?
さて、少しバックアップしましょう。
Haskellの「undefined」は「bottom」値の例です(⊥で示されています)。このような値は、プログラム内の未定義、スタック、または部分的な状態を表します。
ボトムにはさまざまな形式があります。非終了ループ、例外、パターンマッチの失敗など、基本的に、ある意味で定義されていないプログラム内の状態です。この値undefined :: a
は、プログラムを未定義の状態にする値の標準的な例です。
undefined
それ自体は特に特別なものではなく、配線されていません。またundefined
、ボトムイールド式を使用してHaskellを実装できます。たとえば、これは次の有効な実装ですundefined
。
> undefined = undefined
または、すぐに終了します(古いGoferコンパイラはこの定義を使用していました):
> undefined | False = undefined
bottomの主な特性は、式がbottomに評価される場合、プログラム全体がbottomに評価されることです。プログラムは未定義の状態にあります。
なぜあなたはそのような価値が欲しいのですか?まあ、怠惰な言語では、プログラム自体がボトムでなくても、ボトム値を格納する構造や関数を操作できることがよくあります。
たとえば、無限ループのリストは完全に混雑しています。
> 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がとても楽しく表現力豊かな理由の一部です。怠惰の結果、Haskellは特に価値観に細心の注意を払っていbottom
ます。
ただし、明らかに、ボトムの概念はJava、または任意の(合計ではない)言語にも同様に当てはまります。Javaには、「ボトム」値を生成する多くの式があります。
- 参照をnullと比較します(ただし、
null
それ自体ではなく、明確に定義されていることに注意してください)。
- ゼロ除算。
- 範囲外の例外。
- 無限ループなど。
あるボトムを別のボトムに簡単に置き換えることはできません。また、Javaコンパイラはボトム値について多くのことを推論しません。ただし、そのような値はあります。
要約すれば、
- Javaで値を間接参照する
null
ことは、Javaで最下位の値を生成する特定の式の1つです。
- Haskellの
undefined
値は、Haskellでボトム値が必要な場所ならどこでも使用できる一般的なボトムイールド式です。
それが彼らが似ている方法です。
追記
それ自体の問題に関してnull
:なぜそれは悪い形と見なされるのですか?
- まず、Javaは、Haskellのすべての型に暗黙を追加すること
null
と本質的に同等です。Maybe a
a
- 間接参照は、次の場合
null
にのみパターンマッチングと同等です。Just
f (Just a) = ... a ...
したがって、渡される値がNothing
(Haskellの場合)またはnull
(Javaの場合)の場合、プログラムは未定義の状態になります。これは悪いことです:あなたのプログラムはクラッシュします。
したがって、すべてnull
の型に追加することで、誤って値を作成するのがはるかに簡単になりました。型はもはや役に立ちません。あなたの言語はもはやあなたがその特定の種類のエラーを防ぐのを助けていません、そしてそれは悪いことです。bottom
もちろん、他のボトム値はまだあります:例外(のようなundefined
)、または無限ループ。すべての関数に新しい可能性のある障害モードを追加する(逆参照null
する)と、クラッシュするプログラムを簡単に作成できるようになります。