Di GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
Mengapa yang pertama bukan pengecualian bersarang?
Di GHCi:
Prelude> error (error "")
*** Exception:
Prelude> (error . error) ""
*** Exception: *** Exception:
Mengapa yang pertama bukan pengecualian bersarang?
error
khusus dan bukan merupakan mekanisme pengecualian. Untuk pengecualian yang nyata dan dapat ditangkap, lihat Error
monad.
(\f g x -> f (g x)) error error ""
berperilaku berbeda dari (.) error error ""
, meskipun fungsinya setara dengan (.)
. Mungkin ini ada hubungannya dengan flag pengoptimalan yang telah dikompilasi dengan Prelude.
iterate error "" !! n
dan luar biasa fix error
.
error = error
dan memprogram sesuai dengan itu.
Jawaban:
Jawabannya adalah bahwa ini adalah semantik pengecualian yang tidak tepat (agak mengejutkan)
Ketika kode murni dapat ditampilkan untuk mengevaluasi satu set nilai luar biasa (yaitu nilai error
atau undefined
, dan secara eksplisit bukan jenis pengecualian yang dihasilkan di IO ), maka bahasa mengizinkan nilai apa pun dari set itu untuk dikembalikan. Nilai luar biasa di Haskell lebih mirip NaN
kode floating point, daripada pengecualian berbasis aliran kontrol dalam bahasa imperatif.
Gotcha sesekali bahkan untuk Haskeller tingkat lanjut adalah kasus seperti:
case x of
1 -> error "One"
_ -> error "Not one"
Karena kode mengevaluasi satu set pengecualian, GHC bebas memilih satu. Dengan pengoptimalan aktif, Anda mungkin mendapati ini selalu bernilai "Bukan satu".
Mengapa kita melakukan ini? Karena jika tidak, kami akan terlalu membatasi urutan evaluasi bahasa, misalnya kami harus memperbaiki hasil deterministik untuk:
f (error "a") (error "b")
dengan misalnya, mengharuskan itu dievaluasi dari kiri ke kanan jika ada nilai kesalahan. Sangat tidak Haskelly!
Karena kami tidak ingin melumpuhkan pengoptimalan yang dapat dilakukan pada kode kami hanya untuk mendukung error
, solusinya adalah menentukan bahwa hasilnya adalah pilihan non-deterministik dari kumpulan nilai luar biasa: pengecualian tidak tepat! Di satu sisi, semua pengecualian dikembalikan, dan satu dipilih.
Biasanya, Anda tidak peduli - pengecualian adalah pengecualian - kecuali Anda peduli dengan string di dalam pengecualian, dalam hal ini menggunakan error
untuk men-debug sangat membingungkan.
Referensi: Semantik untuk pengecualian yang tidak tepat , Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Proc Desain dan Implementasi Bahasa Pemrograman (PLDI'99), Atlanta. ( PDF )
throw
) dan Anda dapat secara deterministik melempar pengecualian dengan throwIO
.
case error "banana" of (x:xs) -> error "bonobo"
bisa memberi Anda * Exception: bonobo
.