2013-05-27 17 views
8

Bir işlevin sonucu biliniyorsa GHCi hata ayıklayıcısını durdurmak mümkün mü? Ben 'papperlap' ve 'bla' sonuçlarını görmek istiyorum, ŞimdiAra sonuçları bulmak için GHCi breakpoint hata ayıklayıcısını kullanın?

blabla :: [Int] -> Int 
bla  :: Int -> Int 
papperlap :: Int -> Int -> Int 

bla x   = x+x 
papperlap y x = ((y *) . bla) x 
blabla xs  = foldl papperlap 0 x 

:

Örneğin, aşağıdaki kod parçacığını göz önünde bulundurun. Ama sonuç değerlendirildiğinde durmak istediğimi hatırla. Bu nedenle ': kuvvet' kullanılması değerlendirmenin sırasını değiştirdiğinden bu sorunun dışındadır.

': break' komutunu kullandığımda, hata ayıklayıcı durur ancak _result henüz değerlendirilmemiştir. istenen ara sonuç vermezse, hangi aşağıda benim GHCi oturumu bulabilirsiniz:

GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
[1 of 1] Compiling Main    (bla1.hs, interpreted) 
Ok, modules loaded: Main. 
*Main> :break blabla 
Breakpoint 0 activated at bla1.hs:7:1-36 
*Main> :break papperlap 
Breakpoint 1 activated at bla1.hs:6:1-31 
*Main> :break bla 
Breakpoint 2 activated at bla1.hs:5:1-19 
*Main> blabla [1,2,3] 
Stopped at bla1.hs:7:1-36 
_result :: Int = _ 
[bla1.hs:7:1-36] *Main> :step 
Stopped at bla1.hs:7:17-36 
_result :: Int = _ 
xs :: [Int] = [1,2,3] 
[bla1.hs:7:17-36] *Main> :step 
Stopped at bla1.hs:6:1-31 
_result :: Int = _ 
[bla1.hs:6:1-31] *Main> :step 
Stopped at bla1.hs:6:17-31 
_result :: Int = _ 
x :: Int = 3 
y :: Int = _ 
[bla1.hs:6:17-31] *Main> :step 
Stopped at bla1.hs:6:1-31 
_result :: Int = _ 
[bla1.hs:6:1-31] *Main> :step 
Stopped at bla1.hs:6:17-31 
_result :: Int = _ 
x :: Int = 2 
y :: Int = _ 
[bla1.hs:6:17-31] *Main> :step 
Stopped at bla1.hs:6:1-31 
_result :: Int = _ 
[bla1.hs:6:1-31] *Main> :step 
Stopped at bla1.hs:6:17-31 
_result :: Int = _ 
x :: Int = 1 
y :: Int = 0 
[bla1.hs:6:17-31] *Main> :step 
Stopped at bla1.hs:5:1-19 
_result :: Int = _ 
[bla1.hs:5:1-19] *Main> :step 
Stopped at bla1.hs:5:17-19 
_result :: Int = _ 
x :: Int = 1 
[bla1.hs:5:17-19] *Main> :step 
Stopped at bla1.hs:5:1-19 
_result :: Int = _ 
[bla1.hs:5:1-19] *Main> :step 
Stopped at bla1.hs:5:17-19 
_result :: Int = _ 
x :: Int = 2 
[bla1.hs:5:17-19] *Main> :step 
Stopped at bla1.hs:5:1-19 
_result :: Int = _ 
[bla1.hs:5:1-19] *Main> :step 
Stopped at bla1.hs:5:17-19 
_result :: Int = _ 
x :: Int = 3 
[bla1.hs:5:17-19] *Main> :step 
0 
*Main> 

cevap

0

Haskell sizin için değişmez ifadeleri adım adım yok. derleyici sadece derleme zamanında 'etrafta' bulabilirsiniz değişmezleri oluşan herhangi ifadeleri optimize eder çünkü

e = 2*(2+2) 

gibi bir şey hemen 8'e değerlendirecek (ifade bu tip sabit uygulamalı formu olarak adlandırılır).

Şimdi foldl'un tembel olduğunu fark etmelisiniz. Bir listede foldl f'u çağırırsanız, kesinlikle zorlanana kadar tek bir değerlendirme f gerçekleştirmez.

>foldl (+) 0 [1,2,3] 
>foldl (+) a1 [2,3] 
    where a1 = 0+1 
>foldl (+) a2 [3] 
    where a2 = a1+2 
      where a1 = 0+1 

sonunda biz ((0+1)+2)+3) var ve derleyici "Tamam, biz her liste bitkin ve biz en ilkel forma her değerlendirme genişlettik. Değerlendirmenize olanak tanır" diyor. Ve zaten biliyoruz ki, Haskell , bir CAF'nin değerlendirilmesi yoluyla adımını atmayacaktır.

Eğer değerlendirmenin ara değerlerini görmek istiyorsanız, bunları öncelikle üretmek zorundasınız. Bunu yolu foldl aşağıdaki sıkı türüdür:

foldl' f z []  = z 
foldl' f z (x:xs) = let z' = z `f` x 
        in seq z' $ foldl' f z' xs 

nasıl çalıştığını anlamaya bırakacaktır fakat seq a b olacak tam değerlendirebilme a tembel b değerlendirmek için devam etmeden önce.

foldl - foldl' arasındaki değişiklikler hariç olmak üzere, her şeyi olduğu gibi yapın. Değerlendirme aşamasına geçtiğinizde, foldl' işlevinin içinde duraklatıldığında ara göreceksiniz.

+0

Cevabınız için teşekkür ederiz. Ancak, sıkı değerlendirmeye geçmek istediğim şey değil, bu durumda da ': kuvvet' kullanabilirim. Niyetim, sonuç değerleri değerlendirildiğinde 'bla' ve 'papperlap' sonucunu denetleyebilmektir. Ve benzer bir sonucu elde etmek için: 'bla 1 = 2; papperlap 0 1 = 0; bla 2 = 4; papperlap 0 2 = 0; bla 3 = 6; papperlap 0 3 = 0; blabla [1,2,3] = 0' –

3

sizin hemen ayıklama kaygıları için biraz geç olabilir, ama burada ben öyle yapardım olabilir:

blabla :: [Int] -> Int 
bla  :: Int -> Int 
papperlap :: Int -> Int -> Int 

bla x   = (undefined :: Int) 
papperlap y x = ((y *) . bla) x 
blabla xs = foldl papperlap 0 xs 

Şimdi biz bla değerlendirilmesinde istisna elde edersiniz biliyorum.

[1 of 1] Compiling Main    (temp.hs, interpreted) 
Ok, modules loaded: Main. 
λ: :set -fbreak-on-exception 
λ: :trace blabla [1,5,17] 
Stopped at <exception thrown> 
_exception :: e = _ 
λ: :hist 
-1 : bla (temp.hs:6:17-35) 
-2 : bla (temp.hs:6:1-35) 
-3 : papperlap (temp.hs:7:17-31) 
-4 : papperlap (temp.hs:7:1-31) 
-5 : papperlap (temp.hs:7:17-31) 
-6 : papperlap (temp.hs:7:1-31) 
-7 : papperlap (temp.hs:7:17-31) 
-8 : papperlap (temp.hs:7:1-31) 
-9 : blabla (temp.hs:8:13-32) 
-10 : blabla (temp.hs:8:1-32) 
<end of history> 
λ: :back 
Logged breakpoint at temp.hs:6:17-35 
_result :: a 
λ: :list 
5 
6 bla x   = (undefined :: Int) 
        ^^^^^^^^^^^^^^^^^^^ 
7 papperlap y x = ((y *) . bla) x 
λ: :back 
Logged breakpoint at temp.hs:6:1-35 
_result :: a 
λ: :list 
5 
6 bla x   = (undefined :: Int) 
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
7 papperlap y x = ((y *) . bla) x 
λ: :back 
Logged breakpoint at temp.hs:7:17-31 
_result :: Int 
x :: Int 
y :: Int 
λ: :list 
6 bla x   = (undefined :: Int) 
7 papperlap y x = ((y *) . bla) x 
        ^^^^^^^^^^^^^^^ 
8 blabla xs = foldl papperlap 0 xs 

Ve böylece bla sağ tarafı değerlendirilmesi giden yığını görebilirsiniz: Öyleyse GHCi içine bırakalım.Her yerde yapışkan ve hacky görünüyor undefined s koyarak beri

Bu mükemmel değil, ama :hist zaten üzerinde çalışmaya size biraz verir ve işler daha da belirgin yapar geri adım olarak :list kullanarak.

İlgili konular