У GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
Чому перший не є вкладеним винятком?
У GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
Чому перший не є вкладеним винятком?
error
є особливим і насправді не механізмом винятків. Для справжніх, виловлюваних винятків див Error
. Монаду .
(\f g x -> f (g x)) error error ""
поводиться інакше (.) error error ""
, ніж ця функція еквівалентна (.)
. Можливо, це пов’язано з прапорами оптимізації, з якими було скомпоновано Prelude.
iterate error "" !! n
і дивовижний fix error
.
error = error
і програмую відповідно.
Відповіді:
Відповідь полягає в тому, що це (дещо дивно) семантика неточних винятків
Коли чистий код може бути показаний для обчислення набору виняткових значень (тобто значення error
або undefined
, і явно не виду винятків, згенерованих в IO ), тоді мова дозволяє повернути будь-яке значення цього набору. Виняткові значення в Haskell більше схожі NaN
на код з плаваючою комою, а не на винятки на основі керуючих потоків в імперативних мовах.
Час від часу навіть для просунутих хаскелерів є такі випадки, як:
case x of
1 -> error "One"
_ -> error "Not one"
Оскільки код оцінює безліч винятків, GHC може вільно вибрати такий. Якщо ввімкнено оптимізацію, цілком можливо, це завжди оцінюється як "Не одна".
Чому ми це робимо? Оскільки інакше ми надмірно обмежимо порядок оцінки мови, наприклад, нам доведеться зафіксувати детермінований результат для:
f (error "a") (error "b")
наприклад, вимагаючи, щоб воно обчислювалось зліва направо, якщо наявні значення помилок. Дуже не-Хаскеллі!
Оскільки ми не хочемо скалічувати оптимізації, які можна зробити з нашим кодом лише для підтримки error
, рішення полягає в тому, щоб вказати, що результат є недетермінованим вибором із набору виняткових значень: неточні винятки! У певний спосіб повертаються всі винятки, і вибирається один.
Зазвичай вас це не хвилює - виняток є винятком - якщо ви не дбаєте про рядок усередині винятку, і в цьому випадку використання error
для налагодження дуже заплутане.
Список літератури: Семантика для неточних винятків , Саймон Пейтон Джонс, Аластер Рід, Тоні Хоаре, Саймон Марлоу, Фергюс Хендерсон. Розробка та впровадження мов програмування Proc (PLDI'99), Атланта. ( PDF )
throw
), і що ви можете детерміновано кинути виняток за допомогою throwIO
.
case error "banana" of (x:xs) -> error "bonobo"
може дати вам * Exception: bonobo
.