error stack traces/source locations
claus.reinke at talk21.com
Sun May 24 05:49:21 EDT 2009
>> the mapException approach
> I'm afraid it won't work as you hope for functions that return lazy data
> structures. The 'evaluate' implicit in mapException only catches
> top-level errors/exceptions, like 'seq' and not like 'deepSeq'.
Have a look at 'firstLetters2' in the example I provided. Perhaps
it is easier to see if you change the 'map_' to 'map', or at least put
the definition on two lines (since the CPP-based SRCLOC doesn't
include columns), but it is there in any case. The initial call to 'map_'
is not part of the stack trace, nor are any of the recursive calls.
Nor should they be, I think - if 'map' delivers as much as '' or
'undefined : undefined' without raising an error, it has done its job.
If evaluating any part of the non-strict data structure runs into trouble,
the inspection, not the generation, is to blame.
That may be inconvenient when one actually wants to see where
the parts of the data structure came from, but there are established
techniques for forcing strictness, or one can annotate data with
producer info (in ways similar to what Hood does: make sure the
producer info is there if the part is ever inspected, but don't actually
force the part).
Here is a slightly rewritten 'firstLetters2', to illustrate:
firstLetters2 = mapError SRCLOC $ -- 58
map_ (mapError SRCLOC . head) ["hi", "world", "", "!"] -- 59
map_ f  = 
map_ f (h:t) = f1 h : mapError SRCLOC (map_ f2 t) -- 62
where f1 = mapError SRCLOC . f -- 63
f2 = mapError SRCLOC . f -- 64
and here is the relevant part of the output (using -DPLAIN):
Prelude.head: empty list
Neither 58 nor 62 appear in the trace (there is nothing wrong
with 'map_'). The appearance of 63 and 64 in the trace gives
one simple example of how information can be added without
prematurely forcing evaluation (eg, 'head firstLetters2' gives
no trace at all).
More information about the Glasgow-haskell-users