状态monad与谓词

时间:2013-10-21 00:59:48

标签: haskell state-monad

我试图创建一些看起来很像State monad的东西,但也带有一个谓词列表和伴随状态的转换函数。计算的基本步骤如下:

Foo (state, [(pred, t)]) >>= f。将f应用于s,产生s'。然后将每个谓词应用于s'。对于匹配的每个谓词,将关联的转换函数按顺序应用于状态。例如。假设[(p1, t1), (p2, t2), (p3, t3)]fs。如果在f s产生s'后,p1 s'p3 s'都返回True,那么您将执行t1 s'产生s'',然后执行t3 s''产生s''',是计算的结果。

这里有许多活动部件,我觉得正确的方法是在StateT变压器或State monad之上构建它,但是我无法弄清楚从哪里开始。

我觉得这不是很清楚。任何澄清都会使这个更清楚,我们非常感激。

1 个答案:

答案 0 :(得分:8)

我认为你不能制作你要求的单子。正如我在与jozefg的讨论中提到的那样,我们有两个monad法则说

f >=> return = f
return >=> f = f

这意味着在绑定位置不会发生任何“有趣”的事情。特别是,我们不能在每个绑定中运行状态转换函数,因为f >=> return将运行该转换函数而f不会运行,并且这些规则将被破坏。

但是,这并不能阻止我们代表我们进行状态转换的monadic动作。因此,我将概述如何设计跟踪此类过渡并按需运行它们的monad。如果你希望它有用,你肯定需要充实API。基本思想是,我们将存储s和转换表,而不仅仅是s状态。首先,一些样板。

{-# LANGUAGE FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}
import Control.Arrow
import Control.Applicative
import Control.Monad.State

现在,让我们使用s -> s转换。你可以随心所欲地实现它们 - 包括查看谓词和转换列表并选择你想要运行的列表,如果这是你的一杯茶。但这与正确理解其他想法是正交的。我们将定义我们的新类型并为其提供一个Monad实例,该实例仅分派给基础类型。

newtype TStateT s m a = TStateT { unTStateT :: StateT (s, s -> s) m a }
    deriving (Functor, Applicative, Monad)

MonadState实例比使用deriving有点棘手,但仍然非常简单。据推测,我们想假装只有s是州的一部分,所以我们需要集中注意力。我们还将给出runStateT模拟,并选择一个理智的初始转换函数。 (我们稍后会提供一种修改此选择的方法。)

instance Monad m => MonadState s (TStateT s m) where
    state f = TStateT (state (\(s, t) -> let (v, s') = f s in (v, (s', t))))

runTStateT :: Functor m => TStateT s m a -> s -> m (a, s)
runTStateT m s = second fst <$> runStateT (unTStateT m) (s, id)

现在有趣的是。 TStateT的超级大国是它可以随时运行一些过渡。因此,让我们提供一种运行它们的方法以及一种修改转换表的方法。

step :: Monad m => TStateT s m ()
step = TStateT (gets snd) >>= modify

modifyTransitions :: Monad m => ((s -> s) -> (s -> s)) -> TStateT s m ()
modifyTransitions = TStateT . modify . second

这就是一切!