Tıpkı başlığın dediği gibi: Haskell fonksiyon geri dönen birimin değerlendirilmesi için ne gibi garantiler var? Böyle bir durumda herhangi bir değerlendirme yapmaya gerek olmadığını düşünebiliriz, ()
açık bir kesinlik talebi olmadığı sürece derleyici bu tür tüm çağrıları hemen bir değerle değiştirebilir , bu durumda kodun gerekip gerekmediğine karar vermesi gerekebilir dönüş ()
veya alt.
GHCi'de bunu denedim ve tam tersi gibi görünüyor, yani böyle bir fonksiyon değerlendirilmiş gibi görünüyor. Çok ilkel bir örnek
f :: a -> ()
f _ = undefined
Değerlendirme f 1
, varlığı nedeniyle bir hata atar undefined
, bu nedenle bazı değerlendirmeler kesinlikle gerçekleşir. Bununla birlikte, değerlendirmenin ne kadar derin olduğu açık değildir; bazen geri dönen işlevlere yapılan tüm çağrıları değerlendirmek gerektiği kadar derine inmiş gibi görünür ()
. Misal:
g :: [a] -> ()
g [] = ()
g (_:xs) = g xs
Bu kod, sunulduğu takdirde süresiz olarak döngüye girer g (let x = 1:x in x)
. Ama sonra
f :: a -> ()
f _ = undefined
h :: a -> ()
h _ = ()
h (f 1)
dönüşleri göstermek için kullanılabilir ()
, bu durumda bu durumda birim değerli tüm alt ifadeler değerlendirilmez. Buradaki genel kural nedir?
ETA: tabii ki tembellik biliyorum. Derleyici yazarların bu özel durumu genellikle mümkün olandan daha tembel hale getirmesini neyin önlediğini soruyorum.
ETA2: örneklerin özeti: GHC, ()
tam olarak başka herhangi bir tür gibi muamele ediyor gibi görünmektedir , yani, tipte yaşayan normal değerin bir işlevden döndürülmesi gerektiği hakkında bir soru varmış gibi. Böyle bir değerin sadece bir tane olması, (ab) optimizasyon algoritmaları tarafından kullanılmıyor gibi görünmektedir.
ETA3: Haskell dediğimde, GHC'de Haskell değil, Rapor tarafından tanımlanan Haskell'i kastediyorum. Tahmin ettiğim kadar paylaşılmayan bir varsayım gibi görünüyor (ki bu 'okurların% 100'ü' idi), ya da muhtemelen daha net bir soru formüle edebilirdim. Buna rağmen, sorunun başlığını değiştirdiğim için pişmanım, çünkü aslında böyle bir işlev için hangi garantilerin var olduğunu sordu .
ETA4: Görünüşe göre bu soru yoluna girdi ve ben de cevapsız olduğunu düşünüyorum. (Bir 'yakın soru' işlevi arıyordum ama sadece 'kendi sorunuzu cevaplayın' buldum ve cevaplanamadığı için bu rotaya inmedim.) Kimse Rapordan her iki şekilde de karar verecek bir şey getirmedi Bu da güçlü ama kesin olmayan bir 'dil için garanti yok' cevabı olarak yorumlamaya meyilliyim. Tek bildiğimiz, mevcut GHC uygulamasının böyle bir fonksiyonun değerlendirmesini atlamayacağıdır.
Haskell'e bir OCaml uygulaması taşırken asıl sorunla karşılaştım. Orijinal uygulama, birçok türde karşılıklı olarak özyinelemeli bir yapıya sahipti ve kod assert_structureN_is_correct
, 1..6 veya 7'de N için çağrılan bir dizi işlev bildirdi ; bunların her biri, yapı gerçekten doğruysa birimi döndürdü ve değilse bir istisna attı . Ayrıca, bu işlevler doğruluk koşullarını çürüttükçe birbirlerini çağırdılar. Haskell'de bu, Either String
monad kullanılarak daha iyi ele alındı , bu yüzden onu bu şekilde kopyaladım, ancak teorik bir sorun olarak kaldı. Tüm girişler ve cevaplar için teşekkürler.
f 1
"değiştirilir" undefined
.
... -> ()
1) sonlanabilir ve geri dönebilir ()
, 2) bir istisna / çalışma zamanı hatası ile sonlanabilir ve hiçbir şey döndüremez veya 3) ayrışır (sonsuz özyineleme). GHC yalnızca 1) olabileceğini varsayarak kodu optimize etmez: f 1
talep edilirse , değerlendirmesini ve geri dönüşünü atlamaz ()
. Haskell semantiği bunu değerlendirmek ve 1,2,3 arasında neler olduğunu görmek.
()
Bu soruda (tip veya değer) gerçekten özel bir şey yok . Aynı gözlemler () :: ()
, örneğin 0 :: Int
her yerle değiştirirseniz gerçekleşir . Bunların hepsi tembel değerlendirmenin sıkıcı eski sonuçlarıdır.
()
tip değeri vardır ()
ve undefined
.
h1::()->() ; h1 () = ()
veh2::()->() ; h2 _ = ()
. Her iki çalıştırınh1 (f 1)
veh2 (f 1)
ve bu sadece ilki taleplerini bkz(f 1)
.