停止/腌制/取消/恢复计算

时间:2014-01-03 19:33:56

标签: haskell computation

是否有任何Haskell方法可以停止/腌制/取消/恢复计算?

关于这一点的一些相关讨论似乎发生here,但没有提出适当的解决方案。这个讨论还很旧。

如果有某种类型的Event系统用于触发计算的停止和恢复状态,那也很好。

2 个答案:

答案 0 :(得分:3)

执行此操作的一种(部分)方法是在Partial ity monad中操作。

data Partial a = Done a | Step (Partial a)
  deriving Functor

instance Monad Partial where
  return = Done
  Done x >>= f = f x
  Step p >>= f = Step (p >>= f)

使用它,我们可以创建在Partial monad中返回并控制其评估的计算。

reversePartially :: [a] -> Partial [a]
reversePartially = rev [] where
  rev acc []     = Done acc
  rev acc (x:xs) = Step (rev (x:acc) xs)

runN :: Int -> Partial a -> Either (Partial a) a
runN _ (Done a) = Right a
runN 0 (Step p) = Left p
runN n (Step p) = runN (pred n) p

run :: Partial a -> a
run (Step p) = run p
run (Done a) = a

在这里,我们可以使用runN来部分执行计算,在最多n步之后暂停并返回新的,更多计算的thunk或实际结果。我们也可以谨慎对待风,并使用run永远等待Partial monad执行。

有趣的是,在Partial monad中编写内容可以让您控制程序的终止。只要某个计算Step中的每个f都在终止,那么runN n f也始终会终止。这是我们想要暂停功能的一种属性。

使用Partial monad的主要挑战是它必须感染计算的每一步才能工作---其中的任何纯计算最多只需要一个Step。另一个紧密相关的问题是您必须手动使用Step注释代码。最后,Step没有特别保证大小相似或与时钟时间有任何关系。

至少可以通过一些工作线程的并发编程来解决最后一个问题,该线程可以在执行Partial计算时接收“尽快暂停”的信号。

最后,值得注意的是Partial ~ Free Identity提供了Partial的强大概括,使Step的注释更容易一些。

答案 1 :(得分:0)

工作流程包为此提供了一种解决方案:https://hackage.haskell.org/package/Workflow

正如文档所描述的那样:"由于其在永久存储器中的记录状态,计算可以在中断点重新启动。默认情况下,线程状态位于文件中。它可以在另一台计算机上移动和继续。"

在幕后,它使用了一种编写器/状态monad来跟踪Stat类型的操作,其中Stat是一种跟踪您的进度和上下文的方式,如下所示:

data Stat =  Running (M.Map String (String, (Maybe ThreadId)))
          | Stat{ self      :: DBRef Stat
                , wfName    :: String
                , state     :: Int
                , recover   :: Bool
                , timeout   :: Maybe Integer
                , lastActive:: Integer
                , context   :: (Context, B.ByteString)
                , references:: [(Int,(IDynamic,Bool))]
                , versions  :: [IDynamic]
                }
           deriving (Typeable)