haskell - Debugging unwanted strictness? -


i have problem don't know how reason about. ask if me specific problem, dawned on me ask more general question , better general understanding result. hopefully. here goes:

it's obvious enough when program lazy, because end glaring issues space leaks, example. have opposite problem: program strict. trying tie knots, , find things attempt somehow defeat laziness need. general question is, how 1 debug unwanted strictness?


for completeness, here's specific case: i'm in rws, writer component populates map, , reader component observes final state of map. can't strict map before i've finished populating it. appears no problem values in map, like:

do m <- ask val <- m ! key dosomething val -- etc. 

but (!) fails using error, i'd instead prefer fail using monad's fail. i'd following:

do m <- ask maybe (fail "oh noes") (dosomething) (lookup key m) 

this causes program <<loop>>, don't understand. doesn't seem me should more strict using (!), i'm wrong...

your first example strict in map. following looks print "1", runs it, , program prints 1. of course, requires evaluating m.

main = let m = map.fromlist [(1, print "1")] val <- m ! 1 return val 

you meant write reads map. following not strict, since val not used in case expression.

main = let m = map.fromlist [(1, print "1")] let val = m ! 1 return val 

your second example strict because checks whether result of lookup succeeded in order decide how finish executing do-block. requires reading map. it's equivalent to:

do m <- ask case lookup key m of nothing -> fail "oh noes" x -> dosomething x 

debugging strictness problems

evaluation forced case expression or built-in operators + integers. if suspect program failing because value forced before it's available, want find out value being forced , being forced.

which value forced?

in kind of bug, program attempts evaluate expression depends on result of own evaluation. can use trace track down expression being evaluated. in problem, looks value of m being forced, use trace print message before evaluated:

do m1 <- ask let m = trace "using m" m1 ... 

if "using m" last output program (before <<loop>>), you're getting closer bug. if it's not in output, m isn't being evaluated, problem elsewhere. if follows line in output, program continued executing , error occurred later, problem must somewhere else.

where forced?

this tells evaluation got @ least far before stopping. how far did go? did problem happen later? see that, try putting trace on gets evaluated later. know m evaluated in order decide branch of maybe runs, can put trace @ points.

do m1 <- ask let m = trace "using m" m1 maybe (trace "used m" $ fail "oh noes") (\x -> trace "used m" $ dosomething x) (lookup key m) 

if see "using m" followed "used m" in output, know evaluation of m finished , program kept going. if see "using m" only, program stopped between these points. in particular case, should not see "used m", because maybe forces evaulation of m , causes <<loop>>.


Comments

Popular posts from this blog

javascript - backbone.js Collection.add() doesn't `construct` (`initialize`) an object -

php - Get uncommon values from two or more arrays -

Adding duplicate array rows in Php -