2009-11-25 18 views
7
tick :: State Int Int 
tick = get >>= \n -> 
     put (n+1) >>= \y -> 
     return n 

put (n+1)がこの機能の最終結果にどのように影響するのか混乱しています。この関数は初期状態を変更しないで返してください。私はこれを私の心の中で実行しようとしていますが、私は場所のものを保持するために部屋を使い果たしています。 :\誰かがこのHaskell関数(State Monad関連)を通して私を歩くことができますか?

誰かがこの機能の評価を通じて私を歩くことができたら、本当に役に立ちます。

答えて

10

...どのようにputsが状態を最初に更新していますか?何もせずにそこに座っているようです...

ああ、今私はあなたの質問を理解しています。 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は変わらない一方で、内部の状態はまだ更新されます、ということを示したいと考えています。 tick()を2回実行すると、状態は2回インクリメントされます。

が戻っハスケルに取得するには、ここで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) 

手動>>=returngetをインライン化することにより、さらにあなたのtick例を展開しようとput。国家の仕組みがより明確になることを願っています。

+0

私は5秒であなたを打つ!私自身/後で物事を理解する傾向があるのは奇妙です/私は質問しました。私はその応答に感謝します! :) – Rayne

7

あなたは完全に正しいです。 tickの "result"は "state"の初期値です。

もちろん、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の後で他の計算が行われると、更新された状態を見ることができます。例えば

、(1秒が更新された状態を読み込みます)を2回tickをやって:

-- 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 
+0

私が理解していないことは、これがどのように起こっているかです。状態はどのように更新されますが、戻り値は同じままですか?putsは最初の状態をどのように更新していますか?そこに座って何もしていないようだ。 – Rayne

+0

実際、状態は更新されていますが、戻り値の「n」は変わりません。私の他の答えを参照してくださいhttp://stackoverflow.com/questions/1795785/can-somebody-walk-me-through-this-haskell-function-state-monad-related/1796544#1796544 –

5

それはput (n+1)は影響しませんが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 

を使用して、それを書くために役立つかもしれません計算の結果、状態モナド内に保持されている状態を変更します。

+0

それは本当に役立つわけではありません。私はそれを理解しようとすることができるように私の例をdesugared。私は、この状態変化を起こさせるためにここで何が起こっているのかを把握しようとしています。 – Rayne

+0

かなり、私はgetとputの定義を投稿していただろうが、それは完了したと思う。 – barkmadley

+0

それも役に立たなかったでしょう。 :p 私はすでにこの定義を可能な限り深く見ていました。私の目を逃れていた重要なディテールでした。それはあなたのせいではありません。質問を正しく語れないのは私のせいです。 – Rayne