Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell -- Timing out computations in the Rand monad

I want to evaluate random computations in Haskell with a timeout using the Control.Monad.Random library. The following works just fine:

ghci> import System.Timeout
ghci> import Control.Monad.Random
ghci> timeout 1000 . evalRandIO $ getRandomR (True, False)
Just True

However, this approach does not seem to work if we have a computation of type Rand StdGen a that never terminates (i.e. evaluates to bottom). For example:

ghci> let f = f :: Rand StdGen Bool
ghci> timeout 1000 $ evalRandIO f
Just

Here GHCI prints "Just " and then hangs indefinitely trying to evaluate f. Can someone who knows more about the Haskell runtime than I do explain why this happens, and how to get around it? My guess is that the expression evalRandIO f is evaluated to WHNF and so timeout 10 thinks the computation is going to terminate, but I really have no idea.

like image 961
user3873438 Avatar asked Jul 24 '14 14:07

user3873438


1 Answers

This might make more sense if you were to do something like

> Just x <- timeout 1000 $ evalRandIO f
> :t x
x :: Bool
> x
Interrupted.

The computation itself is completing, namely it's reaching WHNF, so timeout does not catch it. The timeout 1000 function itself completes and returns Just undefined. An example where you can get timeout to catch a bottom evaluation would be

> import Control.DeepSeq
> :set +m    -- Multiline mode
> let f :: Bool
|     f = f
|
> timeout 1000000 $ deepseq f (return f)
Nothing

You'll see that it hangs for a second, then returns Nothing when deepseq does not finish evaluating f so it can perform return f.

So yes, your problem is stemming from the fact that f = f gets evaluated to WHNF instead of NF. In order to force NF, you need to use something like deepseq. Another possibly simpler example would be to just use the $! operator, such as:

> let f :: Rand StdGen Bool
|     f = f
|
> timeout 1000000 $ evalRandIO $! f
Nothing
like image 59
bheklilr Avatar answered Oct 02 '22 23:10

bheklilr