2012-04-09 14 views
18

時間のかかる純粋な計算を "kill"するにはどうすればいいですか?試しました純粋な機能のタイムアウト

import System.Timeout 

fact 0 = 1 
fact n = n * (fact $ n - 1) 

main = do maybeNum <- timeout (10^7) $ (return . fact) 99999999 
      print maybeNum 

ただし、これは動作しません。 (return . fact) 99999999getLineのような「実際の」IO関数に置き換えてください。これは期待どおりに機能します。

+0

興味深いことに、 'ファクト'がIOアクション( 'ファクト0 =リターン1;ファクトn =(n *)\' fmap \ '(ファクト$ n-1)')になると、 'timeout'は期待される。 –

+0

@MatveyAksenov:私はそれが本当のIOアクションだからだとは思いませんが、その再帰が 'fmap'を使って' IO'モナドに移動したためです。 – leftaroundabout

+2

任意のコードと潜在的に悪意のあるコードをタイムアウトさせる必要がある場合は、本当に単純な非割り当てループに対してテストを行ってください。 'let x = x in x'と' let x()= x()in x() 'です。 –

答えて

20

点は

return (fact 999999999) 

は直ちに戻り、タイムアウトをトリガしないことです。後で評価されるサンクを返します。あなたは、戻り値、

main = do maybeNum <- timeout (10^7) $ return $! fact 99999999 
      print maybeNum 

の評価を強制した場合(タイムアウトがスタックオーバーフローの前に起こるように、あなたは十分な大きさのスタックを提供する場合)

それがタイムアウトをトリガする必要があります。

関連する問題