为什么runState签名只有状态参数? [英] Why runState signature has only state argument?
问题描述
这是我平时的日志:
[心情:好,耐心:3] - 上午11:00,我很高兴
ESTIMATE - > bla bla 6,[Mood:Good,Patience:2]
ESTIMATE - > bla bla 1,[心情:好,耐心:1]
Cookies! - > ,[心情:好,耐心:再次3! ]
ESTIMATE - > bla bla 7,[Mood:Good,Patience:2]
ESTIMATE - > bla bla 2,[Mood:Good,Patience:1]
ESTIMATE - > bla bla 9,[心情:坏,耐心:-2] - 够了!
ESTIMATE - > 需要休息一下! [心情:坏,耐心:-1]
估计 - > Deploynig!,[情绪:坏,耐心:0]
估计 - > 午餐时间!,[心情:好,耐心:3] - 好吧,他需要我..
ESTIMATE - > bla bla 6,[Mood:Good,Patience:2]
...
现在,我在工作中的这种模式似乎符合 State
Monad。
newtype State sa = State {runState :: s - > (a,s)}
但我该怎么做?这个签名有一个状态的空间,在我的情况下是(Mood,Patience)
,而不是输入( ESTIMATE
或 Cookies
)。这就像我应该回答,甚至没有听!
所以我的问题是:我如何不仅有状态,而且有辩论的计算与 State
Haskell monad
,一个状态并返回一个输出和一个新状态。所以这个类型将会是 input - >状态 - > (state,output)
。
runState
只是部分应用的有状态计算已经接受了它的输入。还要注意,当你编写有状态函数时(即当你使用>> =
绑定运算符或 do
符号),您可以这样做:将输入作为表达式提供,并且绑定仅负责传递状态 em>。
您可以在不使用返回值的情况下调用 get
,但会丢失。如果你想使用它,你必须使用值< - get
,然后提供值
作为显式输入下一个有状态计算。绑定仅在传递状态时才起作用。
实际示例:考虑函数:
doStuff :: Int - > State Int Int
doStuff x = do
val< - get
put $ val + x + 1
return 0
doStuff
类型正好具有输入 - >状态 - > (状态,输出)
。但输入
部分由 x
参数表示。
一旦你提供了 x
,你可以得到 state - > (state,output)
这正是 runState
所代表的。
实际上不需要有状态动作的参数,因为你可以预先部分地应用它们来获得没有输入的纯态有状态计算(这些是可怕的引号)。
A real-life example: If I'm in a good mood('good state'), when manager asks me about estimates, I give him a solid answer, but dares he to do that 3 times in a row, without some free snacks in between, my mood changes(I get to 'bad state') and the next 3 times he approaches I ask him not to disturb me with any of his nonsense.
Here's a log of my usual day:
[ 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 ]
...
Now this model of me at work seems to fit the State
Monad.
newtype State s a = State { runState :: s -> (a, s) }
But how do I do this? The signature has room for a state, which in my case is (Mood,Patience)
, and not for input (ESTIMATE
or Cookies
). It's like I'm supposed to answer without even listening!
So my question is: How do I make not only Stateful but also Argumentful computation with State
monad of Haskell?
A stateful computation gets an input, a state and returns an output and a new state. So the type will be input -> state -> (state, output)
.
The runState
is just a partially applied stateful computation that has already taken its inputs.
Note also that when you compose stateful functions (i.e. when you use the >>=
bind operator or do
notation) you do exactly this: you supply the inputs as expression and the bind is responsible for passing around only the state.
You can call get
without using its return value, but then it gets lost. If you want to make use of it you have to use value <- get
and then provide the value
as an explicit input for the next stateful computation. The bind only comes into play when passing the state around.
Practical example: consider the function:
doStuff :: Int -> State Int Int
doStuff x = do
val <- get
put $ val+x+1
return 0
The doStuff
type has exactly the pattern input -> state -> (state, output)
. But the input
part is represented by the x
argument.
Once you provide x
you get something of type state -> (state, output)
which is exactly what runState
represents.
So you don't actually need the arguments for stateful actions because you can partially apply them beforehand to obtain "pure stateful computations that have no input" (those are scary quotes).
这篇关于为什么runState签名只有状态参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!