Haskell 带谓词的状态单元组

Haskell 带谓词的状态单元组,haskell,state-monad,Haskell,State Monad,我试图创建一些看起来很像状态单子的东西,但也包含一个谓词列表和状态上附带的转换函数。我设想的计算基本步骤如下: Foo(state,[(pred,t)])>=f。将f应用于s,产生s'。然后将每个谓词应用于s'。对于每个匹配的谓词,将关联的转换函数按顺序应用于状态。例如,假设[(p1,t1)、(p2,t2)、(p3,t3)],f和s。如果在fs产生s'、p1s'和p3s'之后都返回True,则您将执行t1 s'产生s'然后执行t3s'产生s',计算结果 这里有很多活动部件,我觉得正确的方法是在S

我试图创建一些看起来很像状态单子的东西,但也包含一个谓词列表和状态上附带的转换函数。我设想的计算基本步骤如下:

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

这里有很多活动部件,我觉得正确的方法是在StateT transformer或State monad之上构建它,但是我不知道从哪里开始


我觉得这似乎不是很清楚。我们非常感谢您的任何澄清。

我认为您无法满足您的要求。正如我在与jozefg的讨论中提到的,我们有两个单子定律

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

然而,这并不能阻止我们执行一元操作,代表我们运行状态转换。因此,我将简要介绍如何设计一个monad来跟踪这些转换并按需运行它们。如果希望API有用,您肯定需要充实一些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
实例比仅使用
派生
要复杂一些,但仍然非常简单。大概在公开场合,我们想假装只有
s
是国家的一部分,所以我们需要稍微集中注意力。我们还将给出
runStateT
模拟,并选择一个合理的初始转换函数。(稍后我们将给出修改此选项的方法。)


这几乎就是一切

Foo
是新数据类型的构造函数吗?
Foo
构造函数的类型签名是什么。例如,
State
的类型签名是
(s->(s,a))->State sa
。非常感谢!我想在我第六次或第七次通读之后,我终于开始明白这里发生了什么。我不太清楚的一点是
runTStateT
的类型是如何工作的。在ghci中,当我执行
:t((fst))
时,它表示
(函子f1,函子f)=>f(f1(b,b1))->f(f1 b)
。然而,
runStateT
的返回类型是
m(a,s)
,这与
((fst))
所期望的不匹配。那么这到底是怎么回事?@Dwilson是的,我对
((fst))
有点担心。这里的技巧是,
(,)a
是一个
函子。可能使用
(第二个fst)
会更清晰。在幕后发生了很多事情。箭头、应用程序、函子。我以前曾深入研究过所有这些东西,试图了解如何处理它们,但结果总是空洞无物。这将所有这些结合在一个美丽的机器中,最终开始有意义。我可能从这个答案中学到了比过去三个月我自己学到的更多的东西。非常感谢你。
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)
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