|
|
|
|
|
by xyzzyz
1571 days ago
|
|
The transformations usually can and should be implemented in a way that preserves the original call stack information. However, you are right that laziness makes backtraces less useful: they still are correct, but they pop up in completely unexpected moment. For example, you do something like “let x = f y in return (g x)”, where x is a (lazy) list, and g :: IO [U] -> V for some types U and V. Then somewhere deep into g’s callstack, 123th element is accessed, which forces its computation, which results in exception. You then get an error, and backtrace should naturally come from function f, but in fact it actually happened while executing g, and if g is missing from the trace, a natural intuition from strict languages would suggest that error happened before execution entered g, because f is called before g, which gets its return value. |
|