Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell functions which time out [duplicate]

import Math.NumberTheory.Primes (factorise)
import System.Timeout (timeout)
import Control.Monad (liftM)

type RetType = [(Integer, Int)] -- factorise's return type

-- proposed function
timedFact :: Integer -> Integer -> Either RetType Integer
timedFact u n = ?

Trying to understand how to write a wrapper function for factorise which times out after u usec. If it succeeds it returns RetType otherwise it returns Integer (what was passed in)

I'm kind of new to Haskell. I understand a timeout requires working in the IO Monad but I'm having trouble pulling back the appropriate result. (Note: I'm not married to Either. Maybe RetType would be fine, too).

Thanks for any help

like image 563
user3424410 Avatar asked Oct 01 '15 01:10

user3424410


1 Answers

Looking at the type, timeout :: Int -> IO a -> IO (Maybe a), it could be used as

import Math.NumberTheory.Primes (factorise)
import System.Timeout (timeout)
import Control.Exception (evaluate)
import Control.DeepSeq (force)

timedFact :: Int -> Integer -> IO (Maybe [(Integer, Int)])
timedFact u = 
      timeout u . evaluate . force . factorise 

Testing:

 #> timedFact 3000000 1231231231223234234273434343469494949494499437141
Nothing
(3.04 secs, 2639142736 bytes)

 #> timedFact 4000000 1231231231223234234273434343469494949494499437141
Just [(1009,1),(47729236307,1),(125199345589541,1),(204202903382078984027,1)]
(3.07 secs, 2662489296 bytes)

update: as user2407038 says in the comments (thanks!),

timedFact u n = timeout u (return $!! factorise n)

also works. ($!!) comes from Control.DeepSeq too. To quote the docs, "In the expression f $!! x, x is fully evaluated before the function f is applied to it".

like image 110
Will Ness Avatar answered Oct 23 '22 01:10

Will Ness