5

是否有任何 Haskell 方法可以停止/酸洗/解酸/恢复计算?

这里似乎发生了一些关于此的相关讨论,但没有提出适当的解决方案。那个讨论也很老了。

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

4

2 回答 2

3

一种(部分)方法是在Partiality 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)

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

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永远等待Partialmonad 执行。

有趣的是,在 monad 中编写内容Partial可以让您对程序的终止进行一些控制。只要Step某些计算f中的每个都在终止,那么runN n f它也总是在终止。这是我们希望函数暂停的一种属性。

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

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

最后,非常值得注意的是,Partial ~ Free Identity它很好地概括了 s 的功能,Partial这使得注释Steps 更加容易。

于 2014-01-04T02:17:10.133 回答
0

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

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

在底层,它使用了一种 writer/state monad 来跟踪你的行为类型StatwhereStat是跟踪你的进度和上下文的一种方式,如下所示:

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)
于 2015-03-04T16:50:30.303 回答