Monads可以做许多惊人的,疯狂的事情.他们可以创建具有值叠加的变量.它们可以允许您在计算之前访问未来的数据.它们可以让您编写破坏性更新,但不是真的.然后延续monad让你打破人们的思想!通常是你自己的.;-)
但这是一个挑战:你能制作一个可以暂停的单子吗?
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
,具有明显的语义).通常情况下,像这样的monad具有某种"运行"功能,它运行计算并将您送回最终状态.但Pause
它是不同的:它提供了一个step
函数,它运行计算直到它调用魔法yield
函数.这里计算暂停,返回给调用者足够的信息以便稍后恢复计算.
额外的awesomness:允许调用者修改step
调用之间的状态.(例如,上面的类型签名应该允许这样做.)
使用案例:编写执行复杂操作的代码通常很容易,但是要将其转换为也在其操作中输出中间状态的总PITA .如果您希望用户能够在执行过程中途改变某些内容,那么事情变得非常复杂.
实施思路:
显然它可以用线程,锁和IO
.但我们能做得更好吗?;-)
继续monad疯狂的东西?
也许是某种编写器monad,yield
只记录当前状态,然后我们可以step
通过迭代日志中的状态来"假装" 它.(显然这排除了改变步骤之间的状态,因为我们现在并没有真正"暂停"任何东西.)