Hookell computation time related

I am writing a game AI in Haskell and I want to search for a game state tree for a certain amount of time (i.e. I always want the AI โ€‹โ€‹to take 3 seconds to decide what needs to be done)

How can I do this in a pure language like Haskell? I expect that I will need to dive into streams and such, but I would prefer to minimize as much as possible.

+7
source share
3 answers

One idea: Combine the timeout (suggested by @MathematicsOrchid) with mutable variables from SafeSemaphore to store intermediate values โ€‹โ€‹each time your process calculates a partial result:

 import Control.Monad import Control.Concurrent.MSampleVar import System.Timeout fac :: Integer -> Integer fac 0 = 1 fac n = n * fac (n - 1) tmo :: Int -> ((a -> IO ()) -> IO ()) -> IO (Maybe a) tmo ms f = do mvar <- newSV Nothing timeout ms (f (writeSV mvar . (Just $!))) readSV mvar longComp :: (Integer -> IO ()) -> IO () longComp save = let loop n = save (fac n) >> loop (n + 1) in loop 0 main :: IO () main = tmo 10000 longComp >>= print 

The function passed to tmo receives an IO action as the first argument, which can be used to save intermediate results. If it receives a timeout, the last stored result is returned. The result is converted to WHNF, so the actual calculation takes place in a thread that stores the result, and not in the one that processes it when it returned from tmo .

In this option, the function passed to tmo should retain its output; it cannot return it. But it would be easy to change it so that its signature is (a -> IO ()) -> IO a .

If you want to keep it clean, I would suggest creating your own monad that encapsulates this idea without letting go of IO .


Update: Please Note:

There is no guarantee that the exception will be delivered quickly, although runtime will strive to ensure that no arbitrary delays occur. In the GHC, an exception can only be raised when the thread reaches a safe point, where is a safe point, where is the memory allocation. Some loops do not perform any memory allocation inside the loop and therefore cannot be interrupted by throwTo.

(from throwTo documentation). In the above example, fac does not allocate any memory, so it will not be interrupted immediately for large numbers.

Update:. I created a small library based on those ideas that define monads for computations that can return partial results before returning the final one or dying at a timeout. See https://github.com/ppetr/timeout-with-results

+5
source

Since the result you are looking for depends on the time, this will inevitably be associated with unclean code.

It looks like System.Timeout from the base package provides the ability to start I / O calculation up to a certain timeout (according to the comment on the left). So all you have to do is write an IO calculation that returns the result you are interested in. However ... the hard part is doing the IO action actually calculates the result, and not just returns an invaluable result. For this, I think you need to evaluate from Control.Exception .

+3
source

System.Timeout is the way to go. He got a very clean interface that doesn't feel at all as if you're messing with threads.

Searching for a game space sounds like a pure calculation, and System.Timeout performs IO actions, so you need to wrap the value in return and evaluate the code strictly enough so that timeout does not execute immediately, believe that the response was returned as soon as it was evaluated by WHNF.

Here's an example here of how the code might look from the same problem as mine.

+2
source

All Articles