是否有任何Haskell方法可以停止/腌制/取消/恢复计算?
关于这一点的一些相关讨论似乎发生here,但没有提出适当的解决方案。这个讨论还很旧。
如果有某种类型的Event系统用于触发计算的停止和恢复状态,那也很好。
答案 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)