2010-07-12 11 views
5

Also arbeite ich durch ein erstes Kapitel Übung von Real World Haskell und ich wollte wissen, ob es eine Option in GHCi gibt, um die Funktionsauswertung mit Parametern bei jedem rekursiven Aufruf zu zeigen. So habe ich zum Beispiel eine einfache Version von 'map' geschrieben, und wenn ich es anwende, möchte ich, dass GHCi jeden rekursiven Aufruf mit tatsächlichen Argumenten (und hoffentlich Ausdrucksergebnissen) anzeigt. Etwas, das mir erlaubt zu verfolgen, was hinter den Kulissen passiert.ghci zeigt den Ausführungsstack

P.S. Während ich dies schreibe, habe ich das Gefühl, dass es durch die Faulheit von Haskells Hinrichtungsmodell begrenzt sein könnte, korrigiere mich, wenn ich falsch liege.

+1

mögliche Duplikate von [Wie bekomme ich einen Callstack in Haskell?] (Http://stackoverflow.com/questions/3220869/how-do-i-get-a-callstack-in-haskell) – rampion

+0

Nicht wirklich ein Duplikat davon. – jrockway

Antwort

2

Sie können Haube für diesen Einsatz:

import Debug.Hood.Observe 

map2 f [] = [] 
map2 f (x:xs) = f x : (observe "map2" $ map2) f xs 

main = runO $ print $ map2 (+1) ([1..10] :: [Int]) 

Wenn Sie es ausführen, wird es jeden Anruf drucken mit den entsprechenden Argumenten map2 und das Ergebnis, das zurückgegeben wurde. Sie sehen etwas wie:

. 
. 
. 
-- map2 
{ \ { \ 10 -> 11 
    , \ 9 -> 10 
    } (9 : 10 : []) 
    -> 10 : 11 : [] 
} 
-- map2 
{ \ { \ 10 -> 11 
    } (10 : []) 
    -> 11 : [] 
} 
-- map2 
{ \ _ [] -> [] 
} 

Für mehr überprüfen Sie die examples.

+0

Bestätigt, in ghci zu arbeiten 7.8.2. –

3

ich verwenden in der Regel Debug.Trace:

import Debug.Trace 

buggy acc xs | traceShow (acc,xs) False = undefined 
buggy acc []  = acc 
buggy acc (x:xs) = buggy (acc + x) xs 

main = print $ buggy 0 [1..10] 

Auf diese Weise können Sie mich sehen, wie der Buggy-Funktion funktioniert:

(0,[1,2,3,4,5,6,7,8,9,10]) 
(1,[2,3,4,5,6,7,8,9,10]) 
(3,[3,4,5,6,7,8,9,10]) 
(6,[4,5,6,7,8,9,10]) 
(10,[5,6,7,8,9,10]) 
(15,[6,7,8,9,10]) 
(21,[7,8,9,10]) 
(28,[8,9,10]) 
(36,[9,10]) 
(45,[10]) 
(55,[]) 
55 

Der Schlüssel ist ein Muster, das nie übereinstimmt, sondern druckt etwas, während es nicht zusammenbringt . Auf diese Weise wird es immer ausgewertet (und druckt daher die Debugging-Informationen), und es ist einfach, an jede Funktion anzuknüpfen. Sie können aber auch sie machen übereinstimmen, wenn Sie nur bestimmte Fälle sehen möchten, wie:

buggy acc [] = acc 
buggy acc (x:xs) | traceShow (acc, x, xs) True = buggy (acc + x) xs 

Nur dann erhalten Sie Debug-Ausgaben an der nicht-Basis-Fall:

(0,1,[2,3,4,5,6,7,8,9,10]) 
(1,2,[3,4,5,6,7,8,9,10]) 
(3,3,[4,5,6,7,8,9,10]) 
(6,4,[5,6,7,8,9,10]) 
(10,5,[6,7,8,9,10]) 
(15,6,[7,8,9,10]) 
(21,7,[8,9,10]) 
(28,8,[9,10]) 
(36,9,[10]) 
(45,10,[]) 
55 

YMMV.