I’d like to figure out in general how to use mutable state in the computation of lazy lists.
For instance, here is a naive Sieve of Eratosthenes implemented using a mutable array (source):
import Control.Monad.ST
import Data.Array.ST
import Data.Array.Unboxed
import Control.Monad
import Data.List
prime :: Int -> UArray Int Bool
prime n = runSTUArray $ do
arr <- newArray ( 2 , n ) True :: ST s ( STUArray s Int Bool )
forM_ ( takeWhile ( \x -> x*x <= n ) [ 2 .. n ] ) $ \i -> do
ai <- readArray arr i
when ( ai ) $ forM_ [ i^2 , i^2 + i .. n ] $ \j -> do
writeArray arr j False
-- yield i ???
prime n returns an array of booleans which denote which numbers are prime.
Is there a way to use this approach to create a lazy-list of those primes? It would be like adding a yield i right after the writeArray statement.
The smallest modification of your program to achieve lazyness is probably to switch to the lazy ST monad (http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Monad-ST-Lazy.html), where this code would work:
The error call is just to demonstrate the true lazy nature of the result:
If you want to avoid the intermediate list of
Maybes, you can, for example, use this code: