7
tick :: State Int Int
tick = get >>= \n ->
       put (n+1) >>= \y ->
       return n

put (n+1)この関数の最終結果にどのような影響があるのか​​、私は混乱しています。この関数は初期状態を変更せずに返す必要があるようです。私はこれを頭の中で実行しようとしていますが、物事を所定の位置に保持するためのスペースが不足し続けています。:\

誰かがこの関数の評価を私に教えてくれるなら、それは本当に役に立ちます。

4

3 に答える 3

10

...そもそも状態を更新するのはどうですか?何もせずにそこに座っているようです...

ああ、今私はあなたの質問を理解しています。あなたはput(そしてget)どのように機能するのか疑問に思っていますよね?

たぶんJavaScriptの例が役立つでしょう(実際の可変状態の言語):

var s; // mutable state
function get() { return s; }
function put(x) { s = x; }

function tick() {
    var n = get();
    put(n + 1);
    return n;
}

nこれは、変更はありませんが、内部状態が更新されることを示していると思います。2回実行するtick()と、状態が2回インクリメントされます。

Haskellに戻るために、Stateモナドの(関連する部分)の完全な定義は次のとおりです。

newtype State s a = State { runState :: s -> (a, s) }

instance Monad (State s) where
    return a = State $ \s -> (a, s)
    m >>= k  = State $ \s -> let
        (a, r) = runState m s
        in runState (k a) r

get   = State $ \s -> (s, s)
put s = State $ \_ -> ((), s)

次に、、、およびを手動でインライン化して、tick例をさらに拡張してみてください。うまくいけば、州がどのように機能するかがより明確になるでしょう。>>=returngetput

于 2009-11-25T12:14:56.663 に答える
7

あなたは完全に正しいです。tick「関数」の「結果」は状態の初期値です。

もちろん、これは実際の「関数」ではなく、結果を生成する前に状態tickを読み書きできる計算です。 この場合、状態は更新されますが、状態の元の値を返しています。

-- 4 is the inital state
ghci> runState tick 4
(4, 5)
-- 4 is the result of the tick computation, 5 is the updated state

この場合、内部tickで状態を再度検査することはないため、変更された状態は表示されません。ただし、の後に他の計算が行わtickれると、更新された状態を確認できます。

たとえば、2回実行tickします(2回目は更新された状態を読み取ります)。

-- 4 is the inital state
ghci> runState (tick >> tick) 4
(5, 6)
-- 5 is the result of the tick computation executed twice,
-- 6 is the updated state
于 2009-11-25T10:25:06.613 に答える
5

do表記法を使用して書くと役立つ場合があります

tick :: State Int Int
tick = do
    n <- get    -- get the state
    put (n+1)   -- save an incremented state
    return n    -- return the original state

は計算結果に影響をput (n+1)与えませんが、状態モナド内に保持されている状態を変更します。

于 2009-11-25T10:31:36.593 に答える