2009-04-28 10 views
14

Czy istnieje sposób, aby wyświetlić etapy redukcji w haskell, to znaczy śledzenie wywołań funkcji rekursywnych? Na przykład, schemat chez zapewnia nam trace-lambda. Czy w Haskell jest odpowiednia forma?Zobacz kroki redukcji w Haskell

+0

Istnieje ogromna różnica w stosunku do Schematu; Haskell jest leniwy, więc faktyczna ocena może nastąpić daleko po rozmowie. – bortzmeyer

Odpowiedz

7

Możesz spróbować wstawiać Debug.Trace.trace w miejscach, które chcesz śledzić, ale ma to tendencję do (a) generowania nieoczekiwanie danych wyjściowych poza kolejnością, ponieważ instrukcja trace może należeć do Thunk, który nie jest do tej pory oceniany z dala od pierwotnego połączenia i (b) zmieniając zachowanie środowiska wykonawczego programu, jeśli śledzenie wymaga oceny rzeczy, które w przeciwnym razie nie zostałyby ocenione (jeszcze).

Czy to służy do debugowania? Jeśli tak ...


Hat modyfikuje swój kod źródłowy do wyjścia śledzenia, które mogą być oglądane po uruchomieniu. Wyjście powinno być bardzo blisko tego, co chcesz: przykład na stronie głównej jest

Na przykład obliczanie wadliwego programu

main = let xs :: [Int] 
      xs = [4*2,5 `div` 0,5+6] 
     in print (head xs,last' xs) 

last' (x:xs) = last' xs 
last' [x] = x 

daje wynik

(8, No match in pattern. 

i Narzędzia do wyświetlania czapek mogą być wykorzystane do zbadania jego zachowania w następujący sposób:

  • Hat-stack

Dla poronionych obliczeń, to obliczenia, które zakończone z komunikatem o błędzie lub zostało przerwane, kapelusz stosu przedstawia w których funkcjonują nazywamy obliczenie zostało przerwane. Czyni to, wyświetlając wirtualny stos wywołań funkcji (redeksów). W związku z tym każde wywołanie funkcji pokazane na stosie spowodowało wywołanie funkcji powyżej. Ocena elementu górnego stosu spowodowała błąd (lub podczas jego oceny obliczenie zostało przerwane). Pokazany stos jest wirtualny, ponieważ nie odpowiada rzeczywistemu stosowi środowiska wykonawczego. Rzeczywisty stos runtime umożliwia leniwą ocenę, podczas gdy wirtualny stos odpowiada stosowi, który byłby użyty do skrupulatnej (ścisłej) oceny.

Stosując ten sam przykład programu, jak wyżej, czapka stosu przedstawia

$ hat-stack Example 
Program terminated with error: 
     No match in pattern. 
Virtual stack trace: 
(Last.hs:6)  last' [] 
(Last.hs:6)  last' [_] 
(Last.hs:6)  last' [_,_] 
(Last.hs:4)  last' [8,_,_] 
(unknown)  main 
$ 

tych dniach GHCi (≥ 6.8.1) jest również wyposażony w debugera:

$ ghci -fbreak-on-exception 
GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer ... linking ... done. 
Loading package base ... linking ... done. 
Prelude> :l Example.hs 
[1 of 1] Compiling Main    (Example.hs, interpreted) 

Example.hs:5:0: 
    Warning: Pattern match(es) are overlapped 
      In the definition of `last'': last' [x] = ... 
Ok, modules loaded: Main. 
*Main> :trace main 
(8,Stopped at <exception thrown> 
_exception :: e = _ 
[<exception thrown>] *Main> :back 
Logged breakpoint at Example.hs:(5,0)-(6,12) 
_result :: t 
[-1: Example.hs:(5,0)-(6,12)] *Main> :hist 
-1 : last' (Example.hs:(5,0)-(6,12)) 
-2 : last' (Example.hs:5:15-22) 
-3 : last' (Example.hs:(5,0)-(6,12)) 
-4 : last' (Example.hs:5:15-22) 
-5 : last' (Example.hs:(5,0)-(6,12)) 
-6 : last' (Example.hs:5:15-22) 
-7 : last' (Example.hs:(5,0)-(6,12)) 
-8 : main (Example.hs:3:25-32) 
-9 : main (Example.hs:2:17-19) 
-10 : main (Example.hs:2:16-34) 
-11 : main (Example.hs:3:17-23) 
-12 : main (Example.hs:3:10-33) 
<end of history> 
[-1: Example.hs:(5,0)-(6,12)] *Main> :force _result 
*** Exception: Example.hs:(5,0)-(6,12): Non-exhaustive patterns in function last' 

[-1: Example.hs:(5,0)-(6,12)] *Main> :back 
Logged breakpoint at Example.hs:5:15-22 
_result :: t 
xs :: [t] 
[-2: Example.hs:5:15-22] *Main> :force xs 
xs = [] 

Chociaż nie jest tak ładny, ma tę zaletę, że jest łatwo dostępny i można go wykorzystać bez ponownej kompilacji kodu.

0

W uściskach jest liczba redukcji, jeśli to pomaga? Alternatywnie, czy możesz użyć czegoś podobnego do uścisku, aby owinąć swój kod, aby uzyskać więcej szczegółów na temat tego, co robi na każdym kroku?

0

Nic nie jest wbudowane w standard Haskell.

Mam nadzieję, że tłumacz graficzny Helium zaproponowałby coś takiego, ale strona milczy na ten temat.

0

Częściowym rozwiązaniem jest użycie vacuum do wizualizacji struktur danych.

Widziałem animacje gif, fold i inne, ale nie mogę ich znaleźć w tej chwili. Myślę, że Cale Gibbard zrobił animacje.