> Friedrich wrote: > >Ok to be more concrete is the laziness "hidden" here? > > > >check_line line sum count = > > let match = matchRegex regexp line > > in case match of > > Just strs -> (sum + read (head strs) :: Integer, count + 1) > > Nothing -> (sum, count)
Yes, part of it. To see why, put yourself into the role of an evaluator for your program. An application of check_line will not be evaluated until necessary, and it becomes necessary only if the result is bound to a pattern (and that binding is needed for some reason). At that point, enough has to be evaluated to determine whether the result is actually a pair or bottom. So what will you do? The body of check_line is a case expression, so you need to sufficiently evaluate its scrutinee. You evaluate enough of matchRegex to see whether the result is Nothing or Just. Let's say it's Just. So you descent into the Just branch, and you see the result is a pair (and not bottom). The elements of the pair have not been evaluated, there was no need to. Also, the arguments to check_line have not been evaluated, except for line. You need to force the evaluation of the elements of the result pair whenever the pair itself is demanded, for example: > >check_line line sum count = > > let match = matchRegex regexp line > > in case match of > > Just strs -> ((,) $! (sum + read (head strs) :: Integer)) $! > > count + 1 > > Nothing -> ((,) $! sum) $! count) (The associativity of ($!) is inconvenient here. I want left-associative ($!). Actually, a strict pair type would be even more convenient here.) On recent GHC with bang-patterns, this short-cut works, too. It's not quite equivalent, because it will create unevaluated thunks, though they won't pile up: > >check_line line !sum !count = > > let match = matchRegex regexp line > > in case match of > > Just strs -> (sum + read (head strs) :: Integer, count + 1) > > Nothing -> (sum, count) Paul Johnson wrote: > Try putting turning the "Just" line into something like > > Just strs -> (seq sum $ sum + read (head strs) :: Integer, seq count > $ count + 1) This doesn't help. First of all, you don't "try putting" anything anywhere. Without understanding what's going on, you'll only create ugly code, bang your head against a wall and still end up with a space leak (been there, done that, bought the t-shirt). Instead, go through the evaluation by hand and/or use a heap profiler to guide you. Then put strictness annotations where needed (and only there). Putting seqs inside the pair is useless, because the problem is that nobody will look there to begin with. Applying seq to sum and count helps, if done outside the pair constructor, but is not quite right. You want the new sums to be evaluated strictly, and while making the function strict in its arguments helps, it stops one step too early. -Udo
signature.asc
Description: Digital signature
_______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell