Haskell'deki istisnalar nasıl çalışır?


87

GHCi'de:

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

İlki neden iç içe geçmiş bir istisna değil?


9
Bu, GHC'nin yapmasına izin verilen bir dönüşümdür: "Ben kendi başına çalışan Derleyiciyim ve tüm _ | _'ler bana benziyor". Bu iki satırı farklı şekilde derleyen uygulama ayrıntılarını mı istiyorsunuz?
shachaf

3
errorözeldir ve gerçekten bir istisna mekanizması değildir. Gerçek, yakalanabilir istisnalar için Errormonad'a bakınız .
Cat Plus Plus

1
Örneğin, işlevin eşdeğer olmasına rağmen , bundan (\f g x -> f (g x)) error error ""farklı davrandığına (.) error error ""dikkat edin (.). Belki de Prelude'un derlendiği optimizasyon bayraklarıyla ilgisi vardır.
shachaf

5
Ayrıca iterate error "" !! nve harika fix error.
Vitus

9
Her zaman öyle taklidi yapıyorum error = errorve buna göre programlıyorum.
Gabriel Gonzalez

Yanıtlar:


103

Cevap, bunun belirsiz istisnaların (biraz şaşırtıcı) semantiği olmasıdır.

Saf kod a değerlendirmek gösterilebilir zaman setinin olağanüstü değerlerden (değerini yani errorya undefinedve açıkça değil istisnalar tür IO üretilen ), sonra dil o setin herhangi bir değer döndürülecek izin verir. Haskell'deki istisnai değerler NaN, zorunlu dillerdeki kontrol akışına dayalı istisnalardan ziyade kayan nokta kodundaki gibidir .

Hatta gelişmiş Haskeller'lar için ara sıra karşılaşılan bir durum aşağıdaki gibi bir durumdur:

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

Kod bir dizi istisna olarak değerlendirildiğinden, GHC birini seçmekte özgürdür. Optimizasyonlar açıkken, bunun her zaman "Bir değil" olarak değerlendirildiğini fark edebilirsiniz.

Bunu neden yapıyoruz? Çünkü aksi takdirde, dilin değerlendirme sırasını aşırı derecede kısıtlardık, örneğin aşağıdakiler için deterministik bir sonuç düzeltmemiz gerekirdi:

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

Örneğin, hata değerleri varsa soldan sağa değerlendirilmesini gerektirerek. Hiç küstahça!

Sadece desteklemek için kodumuzda yapılabilecek optimizasyonları sakatlamak istemediğimizden error, çözüm, sonucun istisnai değerler kümesinden belirleyici olmayan bir seçim olduğunu belirtmektir: kesin olmayan istisnalar! Bir bakıma, tüm istisnalar iade edilir ve biri seçilir.

Normalde umursamazsınız - istisna bir istisnadır - istisnanın içindeki dizeyi önemsemediğiniz sürece, bu durumda errorhata ayıklamak için kullanmak oldukça kafa karıştırıcıdır.


Kaynaklar: Kesin olmayan istisnalar için bir anlambilim , Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Proc Programlama Dilleri Tasarımı ve Uygulaması (PLDI'99), Atlanta. ( PDF )


2
GHC'nin karşılaşılabilecek istisnalardan birini seçtiğini anlıyorum. Ancak sizin "durum" örneğinizde, 1 girişi için "Bir değil" istisnası ile karşılaşılamaz, bu nedenle bunu yine de bir hata olarak sınıflandırırım.
Peaker

8
@Peaker ölü kod elim - iyileştiricinin, bir hatanın sonuç olduğunu görmek için x'e bakmasına gerek yoktur, tüm dallar "aynı" değeri üretir, böylece girdi değerini tamamen yok sayabilir. Kesin olmayan istisnalar altında bir hata değil!
Don Stewart

1
@lpsmith: Tüm istisna türlerinin kesin olmadığını (kullanarak atıldığında throw) ve belirleyici olarak bir istisna atabileceğinizi düşünüyorum throwIO.
FunctorSalad

4
@Peaker Bence haklısın. Eğer belirsiz istisnalar belgesinde ortaya konan kurallara göre oynamak istiyorlarsa, ghc'nin bu ifadeyi optimize etmesi gerektiğini düşünmüyorum.
ağustos

3
Ne kesin olmayan istisnalar kağıt yok demek gibi görünüyor eğer ki durum scrutinee bir hata değeri olup, şubelerden sonra hata değerleri iade edilebilir. Yani case error "banana" of (x:xs) -> error "bonobo"sana verebilirim * Exception: bonobo.
Ben Millwood
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.