Вопрос по exception, haskell – Как работают исключения в Haskell?

86

В GHCi:

Prelude> error (error "")
*** Exception: 
Prelude> (error . error) ""
*** Exception: *** Exception: 

Почему первое не является вложенным исключением?

Обратите внимание, например, что(\f g x -> f (g x)) error error "" ведет себя иначе, чем(.) error error ""даже если эта функция эквивалентна(.), Возможно, это связано с флагами оптимизации, с которыми был скомпилирован Prelude. shachaf
Такжеiterate error "" !! n и удивительныйfix error. Vitus
Я всегда притворяюсь, чтоerror = error и запрограммируйте соответственно. Gabriel Gonzalez
Это преобразование, которое GHC может выполнять: «Я - Компилятор, который работает сам, и все _ | _ одинаковы для меня». Вы спрашиваете детали реализации, которые делают эти две строки компилирующимися по-разному? shachaf
error это особый и не совсем механизм исключения. Для реальных, ловимых исключений смотритеError монада. Cat Plus Plus

Ваш Ответ

1   ответ
100

Ответ в том, что это (несколько удивительно) семантикаimprecise exceptions

Когда чистый код может быть показан для оценкиset исключительных ценностей (то есть значениеerror или жеundefinedи явноnot вид исключенийгенерируется в IO), то язык разрешает возвращать любое значение этого набора. Исключительные значения в Haskell больше похожиNaN в коде с плавающей запятой, а не в исключениях на основе потока управления в императивных языках.

Случайные ошибки для даже продвинутых Хаскеллеров - это такие случаи, как:

 case x of
   1 -> error "One"
   _ -> error "Not one"

Поскольку код оценивается как набор исключений, GHC может выбрать одно. При включенной оптимизации вполне может оказаться, что она всегда оценивается как «Не один».

Почему мы это делаем? Потому что в противном случае мы чрезмерно ограничиваем порядок оценки языка, например нам бы пришлось зафиксировать детерминированный результат для:

 f (error "a") (error "b")

например, требуя, чтобы он оценивался слева направо, если присутствуют значения ошибок. Очень ненормативно!

Поскольку мы не хотим наносить ущерб оптимизации, которая может быть выполнена в нашем коде, просто для поддержкиerrorрешение состоит в том, чтобы указать, что результатом является недетерминированный выбор из набора исключительных значений: неточные исключения! В каком-то смысле все исключения возвращаются, и одно выбирается.

Обычно вы не заботитесь - исключение является исключением - если вы не заботитесь о строке внутри исключения, в этом случае используйтеerror отлаживать очень запутанно.


Рекомендации:Семантика для неточных исключенийСаймон Пейтон Джонс, Аластер Рейд, Тони Хоар, Саймон Марлоу, Фергус Хендерсон. Разработка и реализация языков программирования Proc (PLDI '99), Атланта. (PDF)

@Peaker dead code elim - оптимизатору не нужно смотреть на x, чтобы увидеть, что результатом является ошибка, все ветви выдают «одинаковые» значение, поэтому он может полностью игнорировать входное значение. Не ошибка, неточные исключения!
Какие неточные исключения из бумагиdoes кажется, что еслиcase scrutinee является значением ошибки, то могут быть возвращены значения ошибок из ветвей. Такcase error "banana" of (x:xs) -> error "bonobo" могу дать вам* Exception: bonobo.
@Peaker Я думаю, ты прав. Я не думаю, что ghc должен оптимизировать это выражение, если они хотят играть по правилам, изложенным в неточной статье об исключениях.
@lpsmith: я думаю, что все типы исключений являются неточными (когда выбрасывается с использованиемthrow) и что вы можете детерминистически бросить исключение сthrowIO.
Я понимаю, что GHC выбрал одно из исключений, с которыми можно столкнуться. Но в вашем "случае" Например, «Не один» исключение не может быть найдено для ввода 1, поэтому я все еще классифицирую это как ошибку.

Похожие вопросы