2013-12-23 7 views
15

Kennt jemand eine Funktion, die nur eine bestimmte Menge an Zeit, um eine Funktion auszuführen. Etwas mit einer Typensignatur wie diesem.Haskell Zeitlimit zur Bewertung

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

Ich kann nicht vorstellen, wie zu implementieren, und ich konnte es nicht finden. Der Grund, warum ich frage, ist, ich werde eine Liste aller möglichen Brainfuck Programme machen, und ich möchte diejenigen herausfiltern, die zu lange dauern.

Antwort

20

ist es a dedicated function von System.Timeout:

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

, es zu haben, wie Sie schrieb, benutzen Sie einfach

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

Denken Sie daran, dass Haskell Faulheit jeden Wert bedeutet, ist das, was andere Sprachen könnten „nennen memoised Funktion von Nullargumenten ", so dass Sie die (a->b) -> a -> nicht wirklich brauchen.

+2

Ich hatte keine Ahnung, dass existierte. –

+7

'begrenzt t f x = Timeout t (return $ f x!)' –

+6

Noch besser wäre es: 'Timeout t $ auswerten (fx)' ('evaluate' definiert in' Control.Exception') –

8

Mit dem async Paket können wir race Threads.

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 läuft zwei IO Berechnungen in separate Threads und kehrt je nachdem, welche "gewinnt", so dass wir unseren Faden nur gegen einen threadDelay Rennen.

Beachten Sie, dass wir ($!) zu seq das Ergebnis f a verwenden. Wenn wir das nicht tun, dann gewinnt der Left Thread immer und die Berechnung findet tatsächlich im Hauptthread statt, wenn Sie sie betrachten.