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 всегда побеждает и вычисление на самом деле происходит в основном потоке, когда вы смотрите на него.