最佳答案
Monads 可以做很多惊人的疯狂的事情。它们可以创建包含叠加值的变量。它们允许您在计算未来之前访问未来的数据。他们可以让你写破坏性的更新,但不是真的。然后继续单子允许你 摧毁人们的思想!通常是你自己的。;-)
但是这里有一个挑战: 你能制造一个单子,它可以是 停顿了一下吗?
data Pause s x instance Monad (Pause s) mutate :: (s -> s) -> Pause s () yield :: Pause s () step :: s -> Pause s () -> (s, Maybe (Pause s ()))
Pause
单子是一种状态单子(因此 mutate
具有明显的语义)。通常,这样的单子有某种“ run”函数,它运行计算并返回最终状态。但是 Pause
不同: 它提供了一个 step
函数,该函数运行计算直到调用神奇的 yield
函数。这里暂停计算,将足够的信息返回给调用方,以便稍后恢复计算。
为了获得更好的效果: 允许调用方修改 step
调用之间的状态。(例如,上面的类型签名应该允许这样做。)
用例: 编写执行复杂操作的代码通常很容易,但是要将其转换为操作中的中间状态 输出,则需要一个完整的 PITA。如果您希望用户能够在执行过程中使用 改变,那么事情会变得非常复杂。
实施构思:
显然, 可以通过线程、锁和 IO
来完成。但是我们能做得更好吗? ; -)
有什么疯狂的事情吗?
也许是某种编写器单子,其中 yield
只记录当前状态,然后我们可以通过迭代日志中的状态来“假装”step
。(很明显,这就排除了在步骤之间改变状态的可能性,因为我们现在并没有真正“暂停”任何事情。)