I’m new to Haskell, and I’m writing a paper on it for my Programming Languages class. I want to to demonstrate Haskell’s laziness with some sample code, but I’m not sure if what I’m seeing is actually laziness.
doubleMe xs = [x*2 | x <- xs]
In ghci:
let xs = [1..10]
import Debug.Trace
trace (show lst) doubleMe (trace (show lst) doubleMe (trace (show lst) doubleMe(lst)))
Output:
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[8,16,24,32,40,48,56,64,72,80]
Thanks for your time and help!
Your usage of
tracehere isn’t particularly insightful, or in fact at all. All you do is print out the same list at four different points in the evaluation, that doesn’t tell you anything about the actual state of the program. What actually happens here is thattraceis forced in every doubling step before calculation even starts (when the result list is requested to weak head normal form). Which is pretty much the same as you would get in a language with fully strict evaluation.To see some lazyness, you could do something like
where you can see that only five numbers are doubled, because only five results were requested; even though the list that
doubleLsTracingwas given has 10 entries.Note that
traceis generally not a great tool to monitor “flow of execution”, it’s merely a hack to allow “looking into” local variables to see what’s going on in some function.