
Hello Bullat, first of all, thanks for your lengthy and clear explanation. On Sun, Oct 22, 2006 at 04:08:49PM +0400, Bulat Ziganshin wrote:
f a b = let x = a*b y = a+b in x `seq` y `seq` (x,y)
this f definition will not evaluate x and y automatically. BUT its returned value is not (x,y). its returned value is x `seq` y `seq` (x,y) and when further computation try to use it in any way, it can't put hands on the pair before it will evaluate x and y values. are you understand?
Yes, I do understand. But, as far as I know, "seq" will just evaluate x and y enough to see if they are not bottom. So, if x and y are a deep data structure, they won't be evaluated entirely, right? That is to say:
to get real advantage, you need to build your value sequentially in monad and force evaluation of each step results:
main = do let x = f 1 return $! x let y = f 2 return $! y let z = f 3 return $! z let a = T x y z ..
...
setState ns = modify (\s -> s {mystate = ns})
here you modify state, but don't ensure that string list is evaluated on both levels. well, it will be ok if you ensure evaluation at _each_ call to this function. alternatively, you can force evaluation before assignment by:
setState ns = do return $! map length ns modify (\s -> s {mystate = ns})
this is the crucial point. You are forcing evaluation with $! map length, I'm doing it with writeFile. I do not see very much difference. That's an ad hoc solution. Since I need to write the state, instead of (needlessly) looking for the length of it's members, I write it...;-) By the way, the problem is not ns, but s, the old state. The new state has been evaluated by the code below (when we display the number of lines). So you need to change your code with: do s <- getState modify (\s -> s {mystate = ns}) otherwise you are going to have the same space leak as my original code had. In other word, it is possible to have a user who keeps on loading files without looking at any line (in this case getState is never called and so there is no "return $! mystate s"!). This produces the same as: setState ns = do s <- getState -- that does: return $ mystate s liftIO $ writeFile "/dev/null" s modify (\s -> s {mystate = ns})
if StateT is strict monad transformer, this code don't have space leaks. you create thunks in two places, in one place you already evaluate it, and i wrote what to do in second place.
Yes, indeed. But just because we forced evaluation in a way that `seq` cannot do. Am I right? Thanks a lot for you patience. You did help me a lot. And this is not the first time. I appreciate. Really. Best regards, Andrea