Haskell函数超时

use*_*410 8 io multithreading haskell timeout

import Math.NumberTheory.Primes (factorise)
import System.Timeout (timeout)
import Control.Monad (liftM)

type RetType = [(Integer, Int)] -- factorise's return type

-- proposed function
timedFact :: Integer -> Integer -> Either RetType Integer
timedFact u n = ?
Run Code Online (Sandbox Code Playgroud)

试图理解如何编写因使用过后超时的因子的包装函数.如果成功则返回,RetType否则返回Integer(传入的内容)

我是Haskell的新手.我知道超时需要在IOMonad 工作,但我无法撤回相应的结果.(注意:我没有结婚Either. Maybe RetType也没关系.)

谢谢你的帮助

Wil*_*ess 6

查看类型,timeout :: Int -> IO a -> IO (Maybe a)它可以用作

import Math.NumberTheory.Primes (factorise)
import System.Timeout (timeout)
import Control.Exception (evaluate)
import Control.DeepSeq (force)

timedFact :: Int -> Integer -> IO (Maybe [(Integer, Int)])
timedFact u = 
      timeout u . evaluate . force . factorise 
Run Code Online (Sandbox Code Playgroud)

测试:

 #> timedFact 3000000 1231231231223234234273434343469494949494499437141
Nothing
(3.04 secs, 2639142736 bytes)

 #> timedFact 4000000 1231231231223234234273434343469494949494499437141
Just [(1009,1),(47729236307,1),(125199345589541,1),(204202903382078984027,1)]
(3.07 secs, 2662489296 bytes)
Run Code Online (Sandbox Code Playgroud)

更新:正如user2407038 在评论中所说(谢谢!),

timedFact u n = timeout u (return $!! factorise n)
Run Code Online (Sandbox Code Playgroud)

也有效.($!!)也来自Control.DeepSeq.引用文档,"在表达式f $ !! x中,x在函数f应用于它之前完全评估".

  • @ user2407038,而`evaluate x`看起来很像`return $!x`,事实证明存在重要但微妙的差异.微妙到足以混淆一些主要的GHC实施者; 重要的是,导致一个特殊的`seq #`prinop只是为了正确定义`evaluate`. (5认同)
  • @WillNess @dfeuer`返回$ !! factorise v`有效.`\ uv - > timeout u $ return $ let r = factorise v in r \`deepseq \`r`不起作用,相当于`force(return r)`.但是,`\ uv - > timeout u $ let r = factorise v in r \`deepseq \`return r`确实有效,相当于`return $ !! r`.`evaluate`确实是不必要的,但由于在调用evaluate时已经计算了值,我怀疑它有任何开销,所以它可能无关紧要. (2认同)
  • @ user3424410 1)您知道可以删除评论吗?2)我强烈反对`unsafePerformIO`.**是*为什么它的名字中有"不安全"的原因.无论何时使用它,您都应该提供一个不会引起麻烦的证据.如果你不能这样做,你应该简单地避免使用它,因为你可以很容易搞砸.只需使用`timedFact`作为任何其他`IO`动作. (2认同)