Tembel değerlendirme sayesinde Haskell programı bunu yapmaz (neredeyse yapamaz) göründüğü şeyi yapmaz ).
Bu programı düşünün:
main = putStrLn (show (quicksort [8, 6, 7, 5, 3, 0, 9]))
Hevesli bir dilde, önce quicksort
koşardı, sonra show
sonraputStrLn
. Bir fonksiyonun argümanları, o fonksiyon çalışmaya başlamadan önce hesaplanır.
Haskell'de durum tam tersi. İlk önce işlev çalışmaya başlar. Bağımsız değişkenler yalnızca işlev onları gerçekten kullandığında hesaplanır. Ve bir liste gibi bileşik bir argüman, her bir parçası kullanıldıkça, her seferinde tek parça hesaplanır.
Yani ilk bu programda olur şey olduğunu putStrLn
başlar koşuyor.
GHC'nin gerçeklemesi,putStrLn
String argümanının karakterlerini bir çıktı tamponuna kopyalayarak çalışır. Ancak bu döngüye girdiğinde show
henüz çalışmadı. Bu nedenle, dizeden ilk karakteri kopyalamaya gittiğinde Haskell, o karakteri hesaplamak için gereken show
ve quicksort
çağrılarının kesirini değerlendirir . Sonra bir sonraki karaktere geçer. Her üç functions- yürütülmesi Yani , ve - dönüşümlü olarak. artımlı olarak yürütülür ve nerede kaldığını hatırlamak için değerlendirilmemiş thunks grafiğini bırakır.putStrLn
putStrLn
show
quicksort
quicksort
Bu, şimdiye kadarki herhangi bir programlama diline aşina iseniz, tahmin edebileceğinizden çılgınca farklıdır. quicksort
Haskell'de bellek erişimleri ve hatta karşılaştırma sıralaması açısından gerçekte nasıl davrandığını görselleştirmek kolay değil . Sadece davranışı gözlemleyebilseydiniz, kaynak kodunu değil, hızlı bir sıralama olarak ne yaptığını anlayamazsınız. .
Örneğin, hızlı sınıflandırmanın C sürümü, ilk özyinelemeli aramadan önce tüm verileri bölümler. Haskell sürümünde, sonucun ilk öğesi hesaplanır (ve hatta ekranınızda görünebilir), ilk bölümün çalışması bitmeden önce - aslında üzerinde herhangi bir çalışma yapılmadan öncegreater
.
PS Haskell kodu, hızlı sıralama ile aynı sayıda karşılaştırma yapsaydı, daha hızlı sıralama benzeri olurdu; Kod yazıldığı şekliyle iki kat daha fazla karşılaştırma yapar çünkü lesser
ve greater
bağımsız olarak hesaplanacak şekilde belirtilir, liste boyunca iki doğrusal tarama yapar. Elbette prensip olarak derleyicinin ekstra karşılaştırmaları ortadan kaldıracak kadar akıllı olması mümkündür; veya kod kullanmak için değiştirilebilirData.List.partition
.
PPS Haskell algoritmalarının beklediğiniz şekilde davranmamaya dönüşen klasik örneği, hesaplama asalları için Eratosthenes'in eleği .