haskell – 暂停monad

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

但这里有一个挑战:你能让一个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 ()))

暂停monad是一种状态monad(因此mutate,有明显的语义)。通常,像这样的monad有某种“运行”函数,它运行计算和你回到最终状态。但是Pause是不同的:它提供了一个阶跃函数,它运行计算,直到它调用神奇的yield函数。这里计算被暂停,返回给调用者足够的信息以便稍后恢复计算。

对于额外的真棒:允许调用者修改步骤调用之间的状态。 (例如,上面的类型签名应该允许这样做)。

使用案例:通常很容易编写代码复杂的代码,但是总的PITA将它转换为输出其操作中的中间状态。如果你希望用户能够在执行过程中改变某些事情,事情变得非常快。

实施思路:

>显然,它可以用线程,锁和IO来完成。但我们能做得更好吗? 😉
>与继续monad什么疯狂?
>也许是某种类型的作者monad,其中yield只记录当前状态,然后我们可以通过迭代日志中的状态来“伪装”它。 (显然,这排除了改变步骤之间的状态,因为我们现在不是“暂停”任何东西。)

当然;你只需让任何计算完成一个结果,或暂停自己,给出一个恢复使用的动作,以及当时的状态:

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')

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

http://stackoverflow.com/questions/10236953/the-pause-monad

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:haskell – 暂停monad