一个现实生活中的例子:如果我心情愉快(状态良好'),当经理问我估计时,我会给他一个坚实的答案,但敢于他连续3次连续做了,中间没有一些免费小吃,我的情绪发生了变化(我的状态变得很糟糕),接下来的3次接近我问他不要用任何胡言乱语打扰我。
这是我平时的日志:
[ Mood: Good, Patience: 3 ] -- 11:00 am, I'm happy
ESTIMATE -> "bla bla 6", [ Mood: Good, Patience: 2 ]
ESTIMATE -> "bla bla 1", [ Mood: Good, Patience: 1 ]
Cookies! -> "", [ Mood: Good, Patience: 3 again! ]
ESTIMATE -> "bla bla 7", [ Mood: Good, Patience: 2 ]
ESTIMATE -> "bla bla 2", [ Mood: Good, Patience: 1 ]
ESTIMATE -> "bla bla 9", [ Mood: BAD , Patience: -2 ] -- Enough!
ESTIMATE -> "Need a break!" [ Mood: BAD , Patience: -1 ]
ESTIMATE -> "Deploynig!", [ Mood: BAD , Patience: 0 ]
ESTIMATE -> "Lunch time!", [ Mood: Good, Patience: 3 ] -- Ok he needs me..
ESTIMATE -> "bla bla 6", [ Mood: Good, Patience: 2 ]
...
现在这个我工作的模型似乎适合State
Monad。
newtype State s a = State { runState :: s -> (a, s) }
但是我该怎么做?签名有一个州的空间,在我的情况下是(Mood,Patience)
,而不是输入(ESTIMATE
或Cookies
)。这就像我应该在没有听的情况下回答!
所以我的问题是:我如何使用State
Haskell monad进行有状态计算而且进行有争议的计算?
答案 0 :(得分:8)
有状态计算获取输入,状态并返回输出和新状态。因此类型将为input -> state -> (state, output)
。
runState
只是部分应用的有状态计算,已经取得了输入。
另请注意,当您编写有状态函数时(即使用>>=
绑定运算符或do
表示法时),您可以执行以下操作:将输入作为表达式提供,并且绑定负责传递只围绕州。
您可以在不使用其返回值的情况下调用get
,但随后会丢失。如果要使用它,则必须使用value <- get
,然后提供value
作为下一个有状态计算的显式输入。只有在通过状态时,绑定才会发挥作用。
实际例子:考虑函数:
doStuff :: Int -> State Int Int
doStuff x = do
val <- get
put $ val+x+1
return 0
doStuff
类型具有完全模式input -> state -> (state, output)
。但input
部分由x
参数表示。
提供x
后,您会收到state -> (state, output)
类型的内容,这正是runState
所代表的内容。
因此,您实际上并不需要有状态操作的参数,因为您可以事先部分应用它们以获得没有输入的纯状态计算&#34; (那些是可怕的引用)。
答案 1 :(得分:2)
听起来你正在寻找的不是State
而是StateT
,一个 monad转换器可以为现有的monad添加状态。
newtype StateT s m a = StateT (s -> m (a, s))
如果状态为s
,则StateT s m a
操作会返回m
操作,该操作在运行时会生成结果和新状态。 StateT s
是MonadTrans
的实例:
instance MonadTrans (StateT s) where
--lift :: Monad m => m a -> StateT s m a
lift ma = StateT $
\s -> ma >>= \a -> pure (a, s)
此外,如果m
是Monad
,那么StateT s m
也是如此。
所以,如果你想采取&#34;输入&#34;在某些情况下(例如IO
),您可以自由地这样做:
do
s <- get
input <- lift getLine
when (annoying input && annoyed s) $ put Angry
特别是对于IO
,使用liftIO
通常会更好,这可以提升整堆变形金刚。