Hi all, I am having a problem with the implementation of a program (a genetic algorithm) which requires randomness in it.
It all hinges on the ability to generate something (in the example below an
Int), then provide a function to update it such that the prelude's
iterate
function (or an equivalent) may be used. In my program I require that
both the generation and the updating function contain randomness.
I have drafted a (simplified) example of my problem:
This
code show a trivial case where randomness (and hence the IO monad) is
not used and the first 10 elements of the produced list are printed:
aNum :: Int
aNum = 2
addTwo :: Int -> Int
addTwo = (+) 2
firstTen :: [Int]
firstTen = take 10 (iterate addTwo aNum)
main :: IO ()
main = do
print firstTen
As required the program terminates printing:
[2,4,6,8,10,12,14,16,18,20]
Now
I present my 'conversion' of this trivial case where we both generate a
random number, and add a random amount to it upon each iteration. Again
we only wish to print the first 10:
import System.Random
-- Taken directly from function 'rollDice' in Haskell98 report
randNum :: IO Int
randNum = getStdRandom (randomR (1, 6))
addRand :: Int -> IO Int
addRand x = do
y <- randNum
return (x + y)
firstTen :: IO [Int]
firstTen = do
infiniteNums <- iterateM addRand randNum
return (take 10 infiniteNums)
main :: IO ()
main = do
tenNums <- firstTen
print tenNums
-- Monadic interpretation of prelude iterate definition
iterateM :: Monad m => (a -> m a) -> m a -> m [a]
iterateM f xM = do
x <- xM
mcons xM (iterateM f (f x))
-- Taken from prelude definition of sequence
mcons :: Monad m => m a -> m [a] -> m [a]
mcons p q = p >>= \x -> q >>= \y -> return (x:y)
However this latter case gets stuck in an infinite loop, terminating on a stack overflow.
My question asks why this is the case, when laziness should ensure only the first 10 cases need to be computed.
If anyone wishes to suggest another way entirely to approach this problem that would also be welcome!
Many Thanks,
Dave