2010-07-12 80 views
5

因此,我正在通过Real World Haskell的一些初始章节练习,我想知道GHCi中是否有一个选项使其在每次递归调用时显示函数评估参数。例如,我写了一个简单的'map'版本,当我应用它时,我希望GHCi用实际参数(并希望表达结果)显示每个递归调用。有些东西可以让我跟随幕后发生的事情。ghci显示执行堆栈

P.S.在我写这篇文章时,我有一种感觉,它可能会受到哈斯克尔执行模式懒惰的限制,如果我错了,请纠正我。

+1

可能的重复[如何在Haskell中调用堆栈?](http://stackoverflow.com/questions/3220869/how-do-i-get-a-callstack-in-haskell) – rampion 2010-07-12 03:49:07

+0

不是真的那个重复。 – jrockway 2010-07-12 11:54:36

回答

2

您可以使用遮光罩此:

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]) 

当你运行它,它会打印每个调用与相应的参数MAP2和返回的结果。你会看到类似的东西:

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

欲了解更多,请查阅examples

+0

确认在ghci工作7.8.2。 – 2014-10-01 01:46:25

3

我通常使用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] 

这让我看到了越野车的功能是如何工作的:

(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 

的关键是具有永远不匹配,但打印的东西,而它的不匹配模式。这样它总是得到评估(并因此打印调试信息),并且它很容易适用于任何功能。但你也可以让它搭配,如果你只是想看看某些情况下,如:

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

那么你就只能获得在非基本情况调试输出:

(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 

情况因人而异。