是否有任何 Haskell 方法可以停止/酸洗/解酸/恢复计算?
这里似乎发生了一些关于此的相关讨论,但没有提出适当的解决方案。那个讨论也很老了。
如果有某种类型的事件系统来触发计算的停止和恢复状态,那也很好。
是否有任何 Haskell 方法可以停止/酸洗/解酸/恢复计算?
这里似乎发生了一些关于此的相关讨论,但没有提出适当的解决方案。那个讨论也很老了。
如果有某种类型的事件系统来触发计算的停止和恢复状态,那也很好。
一种(部分)方法是在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 执行。
有趣的是,在 monad 中编写内容Partial
可以让您对程序的终止进行一些控制。只要Step
某些计算f
中的每个都在终止,那么runN n f
它也总是在终止。这是我们希望函数暂停的一种属性。
使用Partial
monad 的主要挑战是它必须感染计算的每一步才能工作——它内部的任何纯计算最多只需要一个Step
. 另一个密切相关的问题是您必须Step
手动使用 s 注释您的代码。最后,Step
s 没有特别保证大小相似或与时钟时间有任何关系。
Partial
最后一个问题至少可以通过工作线程的一些并发编程来解决,该工作线程可以接收信号以在其执行计算时“尽快暂停” 。
最后,非常值得注意的是,Partial ~ Free Identity
它很好地概括了 s 的功能,Partial
这使得注释Step
s 更加容易。
工作流包为此提供了一种解决方案:https ://hackage.haskell.org/package/Workflow
正如文档所述:“由于其在永久存储中的记录状态,计算可以在中断点重新启动。线程状态默认位于文件中。它可以在另一台计算机中移动和继续。”
在底层,它使用了一种 writer/state monad 来跟踪你的行为类型Stat
whereStat
是跟踪你的进度和上下文的一种方式,如下所示:
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)