现实生活中的一个例子:如果我心情很好(“好状态”),当经理问我估计值时,我会给他一个明确的答案,但我敢说,他连续做了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 monad of Haskell?如何使不仅是重要的,而且也是精巧的计算?
发布于 2016-03-23 20:36:50
有状态计算获得输入、状态并返回输出和新状态。所以类型是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 0doStuff类型正好具有模式input -> state -> (state, output)。但是input部分由x参数表示。一旦提供了x,就会得到state -> (state, output)类型的东西,这正是runState所代表的。
因此,您实际上不需要有状态操作的参数,因为您可以预先部分应用它们来获得“没有输入的纯有状态计算”(这些是可怕的引号)。
发布于 2016-03-25 03:02:06
听起来,你要找的不是State,而是StateT,这是一种为现有的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也是。
因此,如果您想在某些上下文中接受“输入”(例如,IO),您可以这样做:
do
s <- get
input <- lift getLine
when (annoying input && annoyed s) $ put Angry特别是对于IO,通常更好的做法是使用liftIO,它可以提升整个变压器堆栈。
https://stackoverflow.com/questions/36188080
复制相似问题