2016-04-24 3 views
0

Почему я не могу использовать значение undefined в haskell? Я имею в виду, что в случае, если:undefined value in haskell

>let t = undefinded 
>if t == undefined then "undefined" else "not undefined" 

Он бросает *** Exception: Prelude.undefined Не Могу ли я использовать неопределенное значение таким образом?

+2

Undefined немного напоминает значение ошибки. Если вы его оцениваете, это вызывает ошибку. Это * не * значение данных. – AJFarmar

+0

Haskell не имеет нулевого указателя/нулевого значения: он был разработан, чтобы избежать ошибки в миллиард долларов (https://en.wikipedia.org/wiki/Null_pointer#History). – chi

ответ

4

Это реализация Prelude в функции undefined:

undefined = error "Prelude.undefined" 

Таким образом, пытаясь оценить undefined возбудит исключение каждый раз. Сравнивая t с undefined, вы применяете эту оценку.

Отметьте, что undefined относится к вычислению, которое никогда не завершается успешно, а не к неизвестному значению (что означает, например, значение undefined в JavaScript, не путайте эти два, это разные вещи).

+0

Есть ли какое-то значение undef для String, Integer ...? –

+6

@ HaskellFun Нет, если есть вероятность, что данная функция может не дать результат, вы должны использовать тип 'Maybe'. – sepp2k

1

undefined в основном является стандартным способом получения “ нижнего значения ”. Нижнее значение (⊥) - единственное значение, которое находится в каждые& dagger; типа, так что вы можете сделать

Prelude> undefined :: Int 
*** Exception: Prelude.undefined 
Prelude> undefined :: Double 
*** Exception: Prelude.undefined 
Prelude> undefined :: String 
"*** Exception: Prelude.undefined 
Prelude> undefined :: IO [Bool] 
*** Exception: Prelude.undefined 

Помимо сообщений исключения, они эквивалентны любой “ ” пользовательского нижнего значения, как

undefined' :: a 
undefined' = undefined' -- this definition creates an infinite loop! 

На этот раз, я не получаю сообщение об ошибке – я должен прервать вручную:

Prelude> undefined' :: Int 
^CInterrupted. 

Фактически стандарт Haskell не гарантирует ничего из этого! Любое вычисление, которое никогда не заканчивается с правильным значением “ ” указанного типа, считается значением ⊥. Поскольку вы можете in general not prove, что вычисление не завершится, невозможно запросить Haskell, если конкретное значение ⊥/undefined.

Если вы хотите иметь значения, которые могут явно (и, возможно, testly) иметь не-значения, просто оберните тип в Maybe!


& dagger; За исключением unboxed types, но это продвинутая низкоуровневая вещь, которая в основном используется для оптимизации.

0

Узор вы ищете это:

let t = Nothing :: Maybe String 
case t of 
    Nothing -> "undefined" 
    Just v -> "defined with value: " ++ v 
3

Возможно, вы рассуждаете по аналогии, полагая, что «неопределенные» является Haskell эквивалент указателя ничтожной или нулевой ссылки на ОО-языке. Это не так. В Haskell неопределенное значение - это просто ошибка, ожидающая своего появления.

Если вам нужно дополнительное значение (тип вещи, на котором вы должны использовать нулевую ссылку на других языках), то вы хотите, возможно. Так, например, Maybe Int является либо «Nothing», либо «Just 5».Так, например, функция «поиск» имеет тип

lookup :: Eq a => a -> [(a, b)] -> Maybe b 

Это говорит о том, что она выглядит вещи в списке пара путем сопоставления по ключевому элементу (типа «а»), а затем возвращает второй элемент в паре (тип «b»). Конечно, он может не найти ключ, поэтому в этом случае он возвращает «Nothing».

lookup "foo" [("foo", 1), ("bar, 2)]  gives  Just 1 
lookup "wib" [("foo", 1), ("bar, 2)]  gives  Nothing 

Чтобы получить результат из «Может быть» вы используете сопоставления с образцом:

case lookup myKey theTable of 
    Just result -> putStrLn $ "Found " ++ show result 
    Nothing -> putStrLn "Key not found" 

Вы можете также использовать «может быть» и функции «fromMaybe» в Data.Maybe. Если вы абсолютно уверены, что значение действительно существует, вы также можете использовать «fromJust», но вам нужно быть очень уверенным, и даже тогда вы, вероятно, должны иметь явный случай для Nothing, чтобы вы могли дать полезное сообщение об ошибке, когда вы оказываетесь неправы.

Edit: объяснение того, почему мы это делаем этот путь

Причина, по которой Haskell не имеет нулевые ссылки, как и другие языки в том, что они по своей сути неоднозначным. Когда любое значение может быть «Null», вы не можете быть уверены, следует ли вам проверять нуль или нет. Таким образом, в приведенном выше примере «lookup» наличие возвращаемого типа «Maybe b» делает его однозначным, и, кроме того, если вы забудете проверить, то компилятор вам скажет. Напротив, если «lookup» вернул ссылку, которая может быть нулевой, как должен знать вызывающий? Что произойдет, если один из аргументов «lookup» также был нулевым. Это будет ошибка? Наличие нулевых ссылок означает, что единственные способы узнать - прочитать код или надеяться, что он попал в документацию.