[Haskell-cafe] ST.Lazy vs ST.Strict

Tobias Olausson tobsan at gmail.com
Sun May 3 19:54:49 EDT 2009


Would unsafeInterleaveST work just as unsafeInterleaveIO in the manner
that it returns immediately, and then is computed lazily?
The idea in the complete program is that one part representing
the CPU will produce a list lazily, which will then be consumed
lazily by another part of the program, which in turn will produce
a lazy list fed to the CPU.
I might add that there was a base case for foo. It turns out i omitted
that for "simplicity". Even stranger, if one adds the following

foo y = do
    if something then return y
    else do
       val <- foo (y+1)
       fail "this is a fail"

Will make the program fail with "this is a fail". Without the fail, that
does not return the computed y. How come?

//Tobias

2009/5/4 Ryan Ingram <ryani.spam at gmail.com>:
> So, I don't know what is causing your problem, but foo will not do
> what you want even with lazy ST.
>
> foo y = do
>   x <- something
>   xs <- foo (y+1)
>   return (x:xs)
>
> Desugaring:
>
> foo y = something >>= \x -> foo (y+1) >>= \xs -> return (x:xs)
> = something >>= \x -> something >>= \x2 -> foo (y+2) >>= \xs2 ->
> return (x2:xs2) >>= \xs -> return (x:xs)
> = something >>= \x -> something >>= \x2 -> foo (y+2) >>= \xs2 ->
> return (x:x2:xs2)
>
> You see that there is an infinite chain of "foo" calls; the lazy ST
> still needs to thread the state through that chain; so in the case of
> foo 0 >>= something_else, the state is _|_ for something_else and you
> will fail if you use read/write/newSTRef after that point.  In fact,
> I'm not sure that lazy ST is very useful :)
>
> My guess is that you want one of
> (1) mdo, when the effects in 'something' only matter once, or
> (2) unsafeInterleaveST, if you just want to be able to traverse the
> (x:xs) list lazily and the references it uses are dead after calling
> foo.
>
>  -- ryan
>
> On Sun, May 3, 2009 at 10:27 AM, Tobias Olausson <tobsan at gmail.com> wrote:
>> Hello!
>> I have a program that is using ST.Strict, which works fine.
>> However, the program needs to be extended, and to do that,
>> lazy evaluation is needed. As a result of that, I have switched
>> to ST.Lazy to be able to do stuff like
>>
>> foo y = do
>>    x <- something
>>    xs <- foo (y+1)
>>    return (x:xs)
>>
>> However, when running the program compiled with ST.Lazy, the
>> following is outputted:
>>   [tobsi at wobsi]$ ./runnerLazy looper.hex
>>   runnerLazy: <<loop>>
>>
>> The very same program compiled with ST.Strict outputs:
>>   [tobsi at wobsi]$ ./runner looper.hex
>>   83298556
>>
>> The code that is actually computing stuff is this:
>> loopSys :: Int -> CPU s Int
>> loopSys cc = do
>>    instr <- fetch
>>    if instr == 0xEA --NOP
>>       then return cc
>>       else do
>>         c <- execute instr
>>         loopSys $! (cc+c)
>>
>> The CPU type looks as follows:
>>   type CPU s a = ReaderT (SysEnv s) (ST s) a
>>
>> The program is run like
>>   runReaderT (loopSys 0)
>> which in turn is being runST'd and then printed
>>
>> Does anyone know why the program just outputs <<loop>>
>> when compiled under ghc 6.10.2, and runs perfectly fine
>> under ghc 6.8.2? The program is compiled with --make and -O2
>>
>>
>> Tobias Olausson
>> tobsan at gmail.com
>> _______________________________________________
>> Haskell-Cafe mailing list
>> Haskell-Cafe at haskell.org
>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>
>



-- 
Tobias Olausson
tobsan at gmail.com


More information about the Haskell-Cafe mailing list