我原本打算将此作为评论发布,但决定再解释一下。
严格来说,get
不“接受”一个论点。我认为很多正在发生的事情都被你没有看到的东西所掩盖——State monad 的实例定义。
get
实际上是 MonadState 类的一个方法。State monad 是 MonadState 的一个实例,提供以下定义get
:
get = State $ \s -> (s,s)
换句话说,get
只返回一个非常基本的 State monad(请记住,monad 可以被认为是计算的“包装器”),其中任何输入s
到计算中都会返回一对s
作为结果。
接下来我们需要看的是>>=
,State 是这样定义的:
m >>= k = State $ \s -> let
(a, s') = runState m s
in runState (k a) s'
因此,>>=
将产生一个新的计算,直到它获得初始状态才会计算(当它们处于“包装”形式时,所有状态计算都是如此)。这种新计算的结果是通过将右侧的任何内容应用于>>=
左侧计算的运行结果来实现的。(这是一个非常令人困惑的句子,可能需要额外阅读一两次。)
我发现对正在发生的一切“脱糖”非常有用。这样做需要更多的输入,但应该使您的问题(从哪里get
得到)的答案非常清楚。请注意,以下应视为伪代码...
test x =
State $ \s -> let
(a,s') = runState (State (\s -> (s,s))) s --substituting above defn. of 'get'
in runState (rightSide a) s'
where
rightSide test =
let test' = x ++ test in
State $ \s2 -> let
(a2, s2') = runState (State $ \_ -> ((), test')) s2 -- defn. of 'put'
in runState (rightSide2 a2) s2'
rightSide2 _ =
-- etc...
这应该清楚地表明我们函数的最终结果是一个新的状态计算,它将需要一个初始值 ( s
) 来完成其余的事情。你提供s
了"testtest"
与你的runState
电话。如果您在上面的伪代码中替换“testtest” s
,您会看到发生的第一件事是我们get
以“testtest”作为“初始状态”运行。这会产生("testtest", "testtest")
等等。
这就是get
你的初始状态“testtest”的地方。希望这可以帮助!