How to determine when an expression is evaluated?

I studied haskell recently, and I understand the concept of lazy evaluation in general. One thing that I have discovered is that it is often difficult to understand exactly when the expression will be evaluated.

Is there a good way to get information about what is happening in terms of evaluation? Ideally, I would like to see something like a stack trace or a list of dependencies that shows when it was necessary to evaluate the expression that needed to be evaluated and what other expressions it depended on should be evaluated.

+5
source share
3 answers

See here an example GHCi debugger session .

+3
+4

with laziness, an expression is really evaluated if its value is needed in the rest of the code. In some situation, you may have a program that does not have access to any elements of the data structure just because you do not use them in your program:

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

Run Results Shows Next Run Time

./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

note that we have the same runtime. try with 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
0
source

All Articles