[Haskell-cafe] Nested unsafePerformIO?
DavidA
polyomino at f2s.com
Thu Apr 8 04:45:20 EDT 2010
Hi,
I am having difficulty debugging a troublesome stack overflow, which I
think might be related to calling unsafePerformIO from within the IO
monad.
So I have the following code:
import System.Random
import System.IO.Unsafe
import Data.Time.Clock
timedIterateIO :: Int -> (a -> a) -> a -> IO a
timedIterateIO durationSecs f x = do
t0 <- getCurrentTime
timedIterateIO' t0 x
where duration' = fromIntegral durationSecs
timedIterateIO' t0 x = do
let y = f x
t <- getCurrentTime
let d = diffUTCTime t t0
if d >= duration' then return y else timedIterateIO' t0
y
f x = unsafePerformIO $ do
m <- randomRIO (1,2)
return (m+x)
The idea of the timedIterateIO function is that it should repeatedly
apply f to x until a specified duration is up. The use case is for
game search, where I want to keep searching until time is up, and then
play the best move I've found at that point.
So the following works:
*Main> timedIterateIO 1 (+1) 0
45580
(1.01 secs, 360357840 bytes)
The following also seems to work:
*Main> unsafePerformIO $ timedIterateIO 1 f 0
67866
(1.25 secs, 394938540 bytes)
Now, in the real use case, I have another function, g let's say. It is
similar to f, in that it uses unsafePerformIO internally to get random
numbers. It's proven to work under normal circumstances, for example:
*Main> (!! 100) $ iterate g x
works, and completes in around a second.
However, the following doesn't work, failing with a stack overflow:
*Main> unsafePerformIO $ timedIterateIO 1 g x
Any ideas?
Thanks, David
More information about the Haskell-Cafe
mailing list