Haskell Ограничение времени на оценку
Кто-нибудь знает о функции, которая позволит только определенное количество времени выполнять функцию. Что-то с типом подписи вроде этого.
limited::Int->(a->b)->a->IO (Maybe b)
Я не могу придумать, как реализовать, и я не смог его найти. Причина, по которой я спрашиваю, я собираюсь составить список всех возможных Brainfuck программ, и я хочу отфильтровать те, которые занимать слишком много времени.
Ответы
Ответ 1
выделенная функция из System.Timeout:
timeout :: Int -> IO a -> IO (Maybe a)
Чтобы это было так, как вы писали, просто используйте
limited t f x = timeout t $ do
let y = f x
y `seq` return y
Помните, что Haskell laziness означает, что любое значение - это то, что другие языки могут называть "memoised function of zero arguments", поэтому вам действительно не нужен (a->b) -> a ->
.
Ответ 2
Используя пакет async
, мы можем race
потоки.
import Control.Applicative
import Control.Concurrent
import Control.Concurrent.Async
limited :: Int -> (a -> b) -> a -> IO (Maybe a)
limited n f a = isLeft <$> race (return $! f a) (threadDelay n)
where isLeft (Left a) = Just a
isLeft _ = Nothing
race
выполняет две вычисления IO
в отдельных потоках и возвращает то, что "выигрывает", поэтому мы просто раскалываем наш поток с threadDelay
.
Обратите внимание, что мы используем ($!)
to seq
результат f a
. Если мы этого не сделаем, поток Left
всегда побеждает и вычисление на самом деле происходит в основном потоке, когда вы смотрите на него.