2013-12-23 27 views
15

関数を実行するのに一定の時間しかかからない関数を知っている人はいますか?このようなタイプの署名を持つもの。評価のHaskellの時間制限

limited::Int->(a->b)->a->IO (Maybe b) 

実装方法を考えることができず、見つからなかった。私が尋ねる理由は、可能なすべてのBrainfuckプログラムのリストを作成するつもりであり、あまりにも時間がかかるものを除外したいのです。

答えて

20

System.Timeoutからa dedicated functionあります:

timeout :: Int -> IO a -> IO (Maybe a) 

だけでHaskellの怠慢は、任意の値を他の言語には「memoised呼ぶかもしれない何をされることを意味することに注意してください

limited t f x = timeout t $ do 
    let y = f x 
    y `seq` return y 

を使用し、それをあなたが書いた方法を持っているために0引数の関数 "となるので、実際には(a->b) -> a ->は必要ありません。

+2

私はそれが存在することは知らなかった。 –

+7

'制限付きt f x =タイムアウトt(return $!f x)' –

+6

さらに良い: 'timeout t $ evaluate(fx)'( 'evaluate'は' Control.Exception'で定義されています) –

8

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は別のスレッドとリターンの2つのIO計算方の一つの「勝利」を実行しますので、我々はちょうどthreadDelayに対する私たちのスレッドをレース。

($!)seqの結果はf aです。我々がしない場合、Leftスレッドは常に勝つので、実際にはメインスレッドで計算が行われます。