2

MonadStateを理解するのは難しいと思います。

その理由は、ほとんどの例がデータ構造のレコード構文と混同している可能性があります。

そこで、レコード構文を使わずにMonadStateを実装してみました。

私が書いた次のコードはコンパイラを通過しましたが、私にはまったくナンセンスに思えます。

これらのコードの何が問題になっていますか?

レコード構文を使用せずにMonadStateを実装する簡単な例はありますか?

data Foo a b = Foo (Maybe ([a],b)) deriving (Show)

unwrapFoo :: Foo a b -> Maybe ([a],b)
unwrapFoo (Foo x) = x

instance Monad (Foo [a]) where
  return x = Foo $ Just ([], x) 
  m >>= f  = case unwrapFoo m of
               Just (_, r) -> f r
               Nothing     -> Foo Nothing 

instance MonadState Int (Foo [a]) where
  get   = Foo $ Just ([], 1)     
  put _ = Foo $ Just ([],())


*Main> get :: Foo [a] Int
Foo (Just ([],1))
*Main> put 3 :: Foo [a] ()
Foo (Just ([],()))
*Main>
4

1 に答える 1

4

それでは、State Monad の基本的な考え方から始めましょう。

newtype MyState s a = MyState (s {- current state -}
                           -> (s {- New state -}, a {- New value -}))

unwrap (MyState f) = f

だから今、実装する必要があります>>=return.

returnとても簡単です:

return a = MyState $ \s -> -- Get the new state
                     (s, a) -- and pack it into our value

つまり、これは現在の状態を新しい値で渡すだけです。

そしていま>>=

(MyState f) >>= g = MyState $ \state -> 
    let (newState, val) = f state
        MyState newF    = g val
    in newF state

したがって、新しい状態を取得し、それを既存の状態モナドにフィードし、結果の値/状態のペアを渡し、そのg結果を返します。

これとレコード構文の違いの総数は、手動で定義する必要があっただけですunwrap

モナドを完成させる

runState = unwrap

get = MyState \s -> (s, s)
put a = MyState \s -> (a, ())
于 2013-05-13T14:32:18.240 に答える