How can I determine when an expression is evaluated?
I've 开发者_JAVA百科recently been learning haskell, and I understand the concept of lazy evaluation in general. One thing that I've discovered though is that it's often difficult to reason about exactly when an expression will be evaluated.
Is there a good way for getting information about precisely what is going on in terms of evaluation? Ideally I'd like to see something like a stack trace or a dependency list that shows when an expression needed to be evaluated, and what other expressions it depended on had to be evaluated.
Another possibility is to use Debug.Trace facility.
See here for an example of GHCi debugger session.
with the lazyness an expression is really evaluated if his value is needed in the rest of the code. In some situation you can have a program which not access to any elements of the data structure just because in your program you haven't use them :
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')
Execution results show the following time execution
./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
we observe that we have the same execution time. let 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
精彩评论