暂停monad [英] The Pause monad

查看:124
本文介绍了暂停monad的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Monads可以做许多惊人的,疯狂的事情。他们可以创建变量来保存值的叠加。在计算它们之前,它们可以允许您访问未来的数据。他们可以让你写破坏性的更新,但不是真的。然后继续monad允许你打破人们的思想! Ususally你自己的。 ; - )



但是,这是一个挑战:你可以创建一个monad,它可以暂停?$ / b>

 
数据暂停sx
实例Monad(暂停s)
mutate ::(s - > s) - >暂停s()
yield: :暂停s()
step :: s - >暂停s() - >(s,Maybe(暂停s()))

Pause monad是一种状态monad(因此 mutate ,具有明显的语义)。通常像这样的monad具有某种运行功能,它运行计算并将您返回到最终状态。但是 Pause 是不同的:它提供了一个 step 函数,它运行计算直到它调用魔术 yield 函数。在这里计算暂停,返回给调用者足够的信息以便稍后恢复计算。



额外的awesomne​​ss:允许调用者修改步骤呼叫。 (例如,上面的类型签名应该允许这样做。)




用例:编写代码通常很容易它做了一些复杂的事情,但是总的PITA将它转换为输出运行中的中间状态。如果您希望用户能够在执行过程的中途修改某些内容,那么情况会非常复杂。



实现思路: p>


  • 很明显可以通过线程,锁和 IO 。但我们可以做得更好吗? ; - )


  • 某种疯狂的事情可能会延续monad?

  • writer monad,其中 yield 只是记录当前状态,然后我们可以通过迭代伪装到 step 日志中的状态。 (很明显,这排除了改变步骤之间的状态,因为我们现在并没有真的暂停任何东西。) >解决方案

当然;您只需让任何计算结果结束,或者暂停自己,给出一个在简历中使用的动作,以及当时的状态:

 数据暂停sa =暂停{runPause :: s  - > (PauseResult s a,s)} 

data PauseResult s a
=完成a
|暂停(暂停)

实例Monad(暂停)其中
返回a =暂停(\s - >(完成a,s))
m>> = k =暂停$ \s - >
案例runPause m s
(完成a,s') - > runPause(k a)s'
(Suspend m',s') - > (挂起(m'>> = k),s')

get ::暂停ss
get =暂停(\ s - >(完成s,s))

put :: s - >暂停s()
put s =暂停(\_ - >(Done(),s))

yield :: Pause s()
yield = Pause( \s->(Suspend(return()),s))

step :: Pause s() - > s - > (Maybe(Pause s()),s)
step m s =
case runPause m s
(Done _,s') - > (Nothing,s')
(暂停m',s') - > (Just m',s')

Monad 实例只是以正常方式对事物进行排序,并将最终结果传递给 k 继续,或者添加剩余的计算以完成暂停。


Monads can do many amazing, crazy things. They can create variables which hold a superposition of values. They can allow you to access data from the future before you compute it. They can allow you to write destructive updates, but not really. And then the continuation monad allows you to break people's minds! Ususally your own. ;-)

But here's a challenge: Can you make a monad which can be paused?

data Pause s x
instance Monad (Pause s)
mutate :: (s -> s) -> Pause s ()
yield :: Pause s ()
step :: s -> Pause s () -> (s, Maybe (Pause s ()))

The Pause monad is a kind of state monad (hence mutate, with the obvious semantics). Normally a monad like this has some sort of "run" function, which runs the computation and hands you back the final state. But Pause is different: It provides a step function, which runs the computation until it calls the magical yield function. Here the computation is paused, returning to the caller enough information to resume the computation later.

For extra awesomness: Allow the caller to modify the state between step calls. (The type signatures above ought to allow this, for example.)


Use case: It's often easy to write code that does something complex, but a total PITA to transform it to also output the intermediate states in its operation. If you want the user to be able to change something mid-way through execution, things get complex really fast.

Implementation ideas:

  • Obviously it can be done with threads, locks and IO. But can we do better? ;-)

  • Something insane with a continuation monad?

  • Maybe some kind of writer monad, where yield just logs the current state, and then we can "pretend" to step it by iterating over the states in the log. (Obviously this precludes altering the state between steps, since we're not really "pausing" anything now.)

解决方案

Sure; you just let any computation either finish with a result, or suspend itself, giving an action to be used on resume, along with the state at the time:

data Pause s a = Pause { runPause :: s -> (PauseResult s a, s) }

data PauseResult s a
    = Done a
    | Suspend (Pause s a)

instance Monad (Pause s) where
    return a = Pause (\s -> (Done a, s))
    m >>= k = Pause $ \s ->
        case runPause m s of
            (Done a, s') -> runPause (k a) s'
            (Suspend m', s') -> (Suspend (m' >>= k), s')

get :: Pause s s
get = Pause (\s -> (Done s, s))

put :: s -> Pause s ()
put s = Pause (\_ -> (Done (), s))

yield :: Pause s ()
yield = Pause (\s -> (Suspend (return ()), s))

step :: Pause s () -> s -> (Maybe (Pause s ()), s)
step m s =
    case runPause m s of
        (Done _, s') -> (Nothing, s')
        (Suspend m', s') -> (Just m', s')

The Monad instance just sequences things in the normal way, passing the final result to the k continuation, or adding the rest of the computation to be done on suspension.

这篇关于暂停monad的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆