KnowledgeHub
Questions
Tags
Users
Search
Alex Rivera
|
Logout
Edit Question
Title
Body
I want to write a function that takes a time limit (in seconds) and a list, and computes as many elements of the list as possible within the time limit. My first attempt was to first write the following function, which times a pure computation and returns the time elapsed along with the result: import Control.DeepSeq import System.CPUTime type Time = Double timed :: (NFData a) => a -> IO (a, Time) timed x = do t1 <- getCPUTime r <- return $!! x t2 <- getCPUTime let diff = fromIntegral (t2 - t1) / 10^12 return (r, diff) I can then define the function I want in terms of this: timeLimited :: (NFData a) => Time -> [a] -> IO [a] timeLimited remaining [] = return [] timeLimited remaining (x:xs) = if remaining < 0 then return [] else do (y,t) <- timed x ys <- timeLimited (remaining - t) xs return (y:ys) This isn't quite right though. Even ignoring timing errors and floating point errors, this approach never stops the computation of an element of the list once it has started, which means that it can (and in fact, normally will) overrun its time limit. If instead I had a function that could short-circuit evaluation if it had taken too long: timeOut :: Time -> a -> IO (Maybe (a,t)) timeOut = undefined then I could write the function that I really want: timeLimited' :: Time -> [a] -> IO [a] timeLimited' remaining [] = return [] timeLimited' remaining (x:xs) = do result <- timeOut remaining x case result of Nothing -> return [] Just (y,t) -> do ys <- timeLimited' (remaining - t) xs return (y:ys) My questions are: How do I write timeOut ? Is there a better way to write the function
Tags (comma-separated)
Save Edits
Cancel