我最近一直在学习haskell,而且我理解懒惰评估的概念。我发现的一件事是,通常很难推断出何时会对表达式进行评估。
有没有一种好方法可以获得有关评估方面正在发生的事情的信息?理想情况下,我希望看到类似于堆栈跟踪或依赖关系列表的内容,以显示何时需要评估表达式,以及必须评估其依赖的其他表达式。
答案 0 :(得分:4)
另一种可能性是使用Debug.Trace设施。
答案 1 :(得分:3)
请参阅此处查看GHCi debugger会话的示例。
答案 2 :(得分:0)
如果在其余代码中需要其值,则实际上会评估表达式。在某些情况下,您可以拥有一个程序,该程序无法访问数据结构的任何元素,因为在您的程序中您没有使用它们:
import System.Environment
-- this first version of the foo function evaluate a list (reversing) but don't use it any more
-- the result show that nothing is compute even the reverse du to the haskell lazyness
foo :: [a] -> IO ()
foo [] = print ("empty list")
foo xs = do let xs' = reverse xs in print ("reversable list")
-- this function evaluate the reversed list's length, so the compiler is oblige here to evaluate
-- both reverse and length
foo' :: [a] -> IO ()
foo' [] = print ("empty list")
foo' xs = do let xs' = reverse xs in print ("reversable list of size " ++ show (length xs'))
main = do
[arg1, arg2] <- getArgs
let listSize = read arg1
let prog = read arg2
if prog == 0 then foo (replicate listSize 'e') else foo' (replicate listSize 'e')
执行结果显示以下时间执行
./stack1 100000000 0 -- calling the foo function with 100000000 elements
"reversable list"
real 0m0.003s
user 0m0.004s
sys 0m0.000s
time ./stack1 0 0 -- calling the foo function with an empty list
"empty list"
real 0m0.003s
user 0m0.004s
sys 0m0.004s
我们观察到我们有相同的执行时间。让我们试试 foo'
time ./stack1 0 1 -- calling foo' with an empty list
"empty list"
real 0m0.003s
user 0m0.004s
sys 0m0.000s
time ./stack1 100000000 2
"reversable list of size 100000000"
real 0m8.662s -- here 8 minutes are spend to reverse and get the list length
user 0m7.944s
sys 0m0.716s