もともとコメントとして投稿するつもりでしたが、もう少し詳しく説明することにしました。
厳密に言えば、get
議論を「とる」ことはありません。起こっていることの多くは、あなたが見ていないもの、つまり州のモナドのインスタンス定義によって隠されていると思います。
get
実際にはMonadStateクラスのメソッドです。StateモナドはMonadStateのインスタンスであり、次の定義を提供しますget
。
get = State $ \s -> (s,s)
言い換えるとget
、非常に基本的な状態モナドを返すだけです(モナドは計算の「ラッパー」と見なすことができることを思い出してください)。ここで、計算への入力は結果としてs
ペアを返します。s
次に確認する必要があるのは>>=
、Stateがこのように定義していることです。
m >>= k = State $ \s -> let
(a, s') = runState m s
in runState (k a) s'
したがって、>>=
新しい計算が生成されます。これは、初期状態になるまで計算されません(これは、「ラップされた」形式のすべての状態計算に当てはまります)。>>=
この新しい計算の結果は、左側にあった計算を実行した結果に、の右側にあるものをすべて適用することによって実現されます。(これはかなり紛らわしい文章であり、さらに1、2回読む必要があるかもしれません。)
起こっていることすべてを「脱糖」することは非常に有用であることがわかりました。そうすることで、より多くの入力が必要になりますが、あなたの質問への答え(どこ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
これにより、関数の最終結果が新しいState計算であり、残りの処理を実行するために初期値()が必要になることが明らかになります。あなたはあなたの呼び出しとs
同じように供給しました。上記の擬似コードで「testtest」を置き換えると、最初に発生するのは「初期状態」として「testtest」を使用して実行することです。これにより、などが得られます。"testtest"
runState
s
get
("testtest", "testtest")
ここでget
、初期状態の「テストテスト」を取得します。お役に立てれば!