首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么runState签名只有状态参数?

为什么runState签名只有状态参数?
EN

Stack Overflow用户
提问于 2016-03-23 20:28:07
回答 2查看 143关注 0票数 7

现实生活中的一个例子:如果我心情很好(“好状态”),当经理问我估计值时,我会给他一个明确的答案,但我敢说,他连续做了3次__,中间没有一些免费的零食,我的心情就变了(我变得“糟糕的状态”),接下来的3次他走近我,让他不要用他的胡说八道来打扰我。

这是我平常的一天的日志:

代码语言:javascript
复制
                             [ 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。

代码语言:javascript
复制
newtype State s a = State { runState :: s -> (a, s) } 

但我该怎么做?签名有用于状态的空间,在我的例子中,状态是(Mood,Patience),而不是输入(ESTIMATECookies)。就像我应该不听就回答似的!

因此,我的问题是:State monad of Haskell?如何使不仅是重要的,而且也是精巧的计算?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-03-23 20:36:50

有状态计算获得输入、状态并返回输出和新状态。所以类型是input -> state -> (state, output)

runState只是一个部分应用的有状态计算,已经接受了它的输入。

还请注意,当您组合有状态函数(即,当您使用>>=绑定运算符或do符号时),您完全可以这样做:您以表达式的形式提供输入,而绑定只负责传递状态。

您可以在不使用其返回值的情况下调用get,但是它会丢失。如果您想要使用它,您必须使用value <- get,然后提供value作为下一个有状态计算的显式输入。绑定只在传递状态时起作用。

实际示例:请考虑以下功能:

代码语言:javascript
复制
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所代表的。

因此,您实际上不需要有状态操作的参数,因为您可以预先部分应用它们来获得“没有输入的纯有状态计算”(这些是可怕的引号)。

票数 8
EN

Stack Overflow用户

发布于 2016-03-25 03:02:06

听起来,你要找的不是State,而是StateT,这是一种为现有的monad添加状态的单点转换器。

代码语言:javascript
复制
newtype StateT s m a = StateT (s -> m (a, s))

给定s类型的状态,StateT s m a操作将返回一个m操作,在运行时该操作将生成一个结果和一个新的状态。StateT sMonadTrans的一个实例

代码语言:javascript
复制
instance MonadTrans (StateT s) where
  --lift :: Monad m => m a -> StateT s m a
  lift ma = StateT $
    \s -> ma >>= \a -> pure (a, s)

此外,如果mMonad,那么StateT s m也是。

因此,如果您想在某些上下文中接受“输入”(例如,IO),您可以这样做:

代码语言:javascript
复制
do
  s <- get
  input <- lift getLine
  when (annoying input && annoyed s) $ put Angry

特别是对于IO,通常更好的做法是使用liftIO,它可以提升整个变压器堆栈。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36188080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档