【问题标题】:Cutting off Lazy List Generation切断惰性列表生成
【发布时间】:2011-02-11 00:31:28
【问题描述】:

我想知道是否有人对如何制作一个将获取列表并仅返回可在 x 时间内生成的术语的函数有任何见解。

例如,我有一个函数需要大约 10 分钟才能返回几个术语。与其猜测我能生成多少项(使用 x ),我只想将一个无限列表输入到我的低效函数中,并让一个单独的函数决定何时超时。

所以是这样的:[5,7,10] = takeUntilTime (10 sec) . inefficientFunction $ [1..]

我对 haskell 很陌生,但我认为我可以编写该函数来在每个新术语生成后检查计时器,如果时间已过则停止。

但是,如果第四个任期是永恒的呢?有没有办法阻止 inefficientFunction 完成第 4 项的生成,即使它已经开始了?

我对一个直截了当的答案寄予厚望,但我很欣赏对此的任何直觉。谢谢。

【问题讨论】:

  • 您想要一个计时器来中断某些值的计算?好吧,我还不知道你想要什么,但它必须是一个 IO 操作。没有纯函数可以做到这一点。
  • 具体用例?这是一个有趣的问题,但你为什么要在“现实世界”中这样做呢?
  • 我最近一直在做 ProjectEuler(projecteuler.net),我喜欢生成快速的实验序列并在 oeis.org 上引用它们。例如,有一些问题的本质是您将长度为 1、2、3 等的棍子首尾相连,然后在这些棍子旁边放置长度为 3、5 等的棍子。问题是找到棍子排列的空间。如果您采用一种简单的方法(即保持运行总数),您几乎无法生成 19 个术语。 (oeis.org/search?q=2,5,15,32,90,189,527,1104,3074,6437) (问题还有很多,所以我没有作弊:))

标签: haskell functional-programming


【解决方案1】:

尚未对其进行太多测试,但这似乎可行,至少在小范围内。

import Control.Concurrent
import Control.Exception
import Control.Monad

takeUntilTime :: Int -> [a] -> IO [a]
takeUntilTime limit list = do
    me <- myThreadId
    bracket (forkIO $ threadDelay limit >> throwTo me NonTermination) killThread
        . const $ tryTake list
  where
    (/:/) = liftM2 (:)
    tryTake list = handle (\NonTermination -> return []) $
        case list of
            [] -> return []
            x:xs -> evaluate x /:/ tryTake xs
ghci> takeUntilTime 1000000 [x | x takeUntilTime 1000000 [最大值 [y `mod` x | y

【讨论】:

  • 这绝对是正确的做法。有关此方法的更多信息,请参阅“尴尬小队”论文的第 5.3 节:google.com/…
  • 并且始终小心将常量提供给 threadDelay。如果您需要maxBound :: Int (2^31-1) 我们的时间,那么最好使用其中一个事件库。
  • 嘿,这正是我要找的,非常感谢!
【解决方案2】:

我想你想要的是这个:System.Timeout

它允许 IO 事件超时。它有一个函数,其类型为:

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

我认为你应该能够使用它。我这样做的方法是使用超时函数和迭代深化方法来为你的函数提供越来越多的内容,直到它起作用。这样,当一个人最终超时时,你就知道你已经走得够远了。

【讨论】:

    【解决方案3】:

    我想你问了两个问题。 1.如何设置从无限列表中获取元素的时间限制。 2. 如何终结一个阻塞函数,或者创建一个非阻塞函数,比如一些网络IO函数。

    关于第二个,你可以参考http://twelvestone.com/forum_thread/view/32028 了解一些想法。 那么对于第一个,你可以假设 inefficientFunction 是非阻塞的。

    【讨论】:

      【解决方案4】:

      ephemient 的回答启发,我想我会发布他的解决方案的两个概括。

      解决方案 1

      import Control.Concurrent
      import Control.Exception
      import Control.Monad
      
      doUntilTime :: Int -> IO a {- must handle NonTermination exception! -} -> IO a
      doUntilTime limit action = do
        me <- myThreadId
        bracket (forkIO $ threadDelay limit >> throwTo me NonTermination) killThread
                 . const $ action
      

      示例

      (/:/) = liftM2 (:)
      tryTake list = handle (\NonTermination -> return []) $
         case list of
           [] -> return []
           x:xs -> evaluate x /:/ tryTake xs
      
      test = do
        res <- doUntilTime 1000000 (tryTake [1..])
        putStrLn (show $ length res)
      

      解决方案 2

      在此解决方案中,您将 默认值输入预递归函数 传递给doUntilTime

      预递归函数以第一个参数(我们称之为self)的风格编写,用于您之前使用递归调用的地方。这使您不必显式处理NonTermination 异常。

      import Control.Concurrent
      import Control.Exception
      import Control.Monad
      
      doUntilTime :: Int -> a -> b -> ((a -> IO b) -> (a -> IO b)) -> IO b
      doUntilTime limit input defaultVal action = do
          me <- myThreadId
          bracket (forkIO $ threadDelay limit >> throwTo me NonTermination) killThread
              . const $ fix action input
        where
          fix f = f (\a -> handle (\NonTermination -> return defaultVal) (fix f a))
      
      (/:/) = liftM2 (:)
      
      -- tryTake is written in a "pre-recursive" style. There are no
      -- occurrences of "tryTake" in the body only occurrences of
      -- "self" (the first parameter)
      tryTake :: ([Int] -> IO [Float]) -> ([Int] -> IO [Float])
      tryTake self list =
         case list of
           [] -> return []
           x:xs -> evaluate (fromIntegral x) /:/ self xs
      
      test = do
        res <- doUntilTime 1000000 [1..] [] tryTake
        print (length res)
      

      【讨论】:

        猜你喜欢
        • 2018-05-19
        • 1970-01-01
        • 1970-01-01
        • 2013-02-01
        • 2010-09-26
        • 2021-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多