Tôi muốn viết một hàm cần có giới hạn thời gian (tính bằng giây) và danh sách, và tính nhiều phần tử trong danh sách càng tốt trong giới hạn thời gian.Tính toán càng nhiều danh sách càng tốt trong một khoảng thời gian cố định
nỗ lực đầu tiên của tôi là đầu tiên viết hàm sau, mà lần một tính tinh khiết và trả về thời gian trôi qua cùng với kết quả:
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)
tôi sau đó có thể xác định chức năng tôi muốn về điều này:
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)
Điều này không hoàn toàn đúng. Thậm chí bỏ qua lỗi thời gian và lỗi dấu phẩy động, cách tiếp cận này không bao giờ dừng tính toán của một phần tử trong danh sách khi nó đã bắt đầu, có nghĩa là nó có thể (và thực tế, bình thường sẽ) vượt quá giới hạn thời gian của nó.
Nếu thay vào đó tôi đã có một chức năng mà có thể đánh giá ngắn mạch nếu nó đã lấy quá dài:
timeOut :: Time -> a -> IO (Maybe (a,t))
timeOut = undefined
sau đó tôi có thể viết các chức năng mà tôi thực sự muốn:
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)
Câu hỏi của tôi là:
- Làm cách nào để viết
timeOut
? - Có cách nào tốt hơn để viết hàm
timeLimited
, ví dụ: một cách không bị lỗi tích lũy dấu phẩy động từ việc thêm chênh lệch thời gian nhiều lần?
Bạn không thể chạy hai luồng mà một chuỗi đếm ngược thời gian và tiêu diệt chuỗi tính toán khi đạt đến giới hạn thời gian của bạn? –
Có thể. Tôi đã không viết rất nhiều mã đồng thời trong Haskell. Làm cách nào để có thể trả lại danh sách được đánh giá một phần? –
Tôi có lẽ sẽ đặt danh sách vào một TVar và chống lại tất cả các nút mới với nó. Chỉ cần thấy rằng STM.TVar có một chức năng gọi là 'registerDelay' cũng có thể hữu ích cho việc đồng bộ hóa hai luồng. –