Ответ 1
Какая разница между undefined в Haskell и null в Java?
Хорошо, немного поднимитесь.
"undefined" в Haskell является примером "нижнего" значения (обозначается ⊥). Такое значение представляет любое undefined, застрявшее или частичное состояние в программе.
Существует множество различных форм дна: неконцевые циклы, исключения, неудачи совпадения шаблонов - в основном любое состояние в программе, которое undefined в некотором смысле. Значение undefined :: a
является каноническим примером значения, которое ставит программу в состояние undefined.
undefined
сам по себе не особенно особенный - его не подключен к сети, и вы можете реализовать Haskell undefined
, используя любое нижестоящее выражение. Например. это допустимая реализация undefined
:
> undefined = undefined
Или немедленно выйти (старый компилятор Gofer использовал это определение):
> undefined | False = undefined
Основное свойство дна состоит в том, что если выражение оценивается снизу, вся ваша программа будет оцениваться снизу: программа находится в состоянии 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
.
Однако, очевидно, концепция дна одинаково хорошо применима к Java или к любому (неточному) языку. В Java существует много выражений, которые дают "нижние" значения:
- сравнение ссылки с нулевым (хотя примечание, а не
null
, которое хорошо определено); - деление на ноль;
- исключения из-за границ;
- бесконечный цикл и т.д.
У вас просто нет возможности подставить одно дно для другого очень легко, а компилятор Java не очень-то разбирается в нижних значениях. Однако такие значения есть.
Таким образом,
- разыменование значения
null
в Java - это одно конкретное выражение, которое дает нижнее значение в Java; - Значение
undefined
в Haskell - это общее генерирующее нижние выражения, которое может использоваться везде, где требуется значение нижнего значения в Haskell.
Как они похожи.
Postscript
Что касается самого вопроса null
: почему он считается плохим?
- Во-первых, Java
null
по существу эквивалентен добавлению неявногоMaybe a
к каждому типуa
в Haskell. - Выделение
null
эквивалентно сопоставлению с образцом только для случаяJust
:f (Just a) = ... a ...
Итак, когда переданное значение равно Nothing
(в Haskell) или null
(в Java), ваша программа достигает состояния undefined. Это плохо: ваша программа вылетает.
Итак, добавив null
к каждому типу, вам просто стало легче создавать значения bottom
случайно - типы больше не помогают вам. Ваш язык больше не помогает вам предотвращать подобную ошибку, и это плохо.
Конечно, другие нижние значения все еще существуют: исключения (например, undefined
) или бесконечные петли. Добавление нового возможного режима отказа к каждой функции - разыменование null
- просто упрощает запись аварийных программ.