8

エラー処理もサポートできる状態モナドを書く必要があります。エラーの原因についての詳細も提供できるため、この目的のために、Either モナドを使用することを考えていました。Maybe モナドを使用して状態モナドの定義を見つけましたが、Maybe の代わりに Each を使用するように変更することはできません。コードは次のとおりです。

newtype StateMonad a = StateMonad (State -> Maybe (a, State))

instance Monad StateMonad where
(StateMonad p) >>= k = StateMonad (\s0 -> case p s0 of 
                                 Just (val, s1) -> let (StateMonad q) = k val in q s1
                                 Nothing -> Nothing)
return a = StateMonad (\s -> Just (a,s))

data State = State
{ log  :: String
, a    :: Int}
4

6 に答える 6

11

(どちらかを使用する代わりに)ExceptTfromを使用することを検討してください。Control.Monad.Trans.Except

import Control.Monad.State
import Control.Monad.Trans.Except
import Control.Monad.Identity

data MyState = S

type MyMonadT e m a = StateT MyState (ExceptT e m) a

runMyMonadT :: (Monad m) => MyMonadT e m a -> MyState -> m (Either e a)
runMyMonadT m = runExceptT . evalStateT m

type MyMonad e a = MyMonadT e Identity a
runMyMonad m = runIdentity . runMyMonadT m

モナドとモナド変換子に慣れていない場合は、最初にそれを行います!それらは大きな助けであり、プログラマーの生産性のパフォーマンスが勝ちます。

于 2010-10-31T22:09:17.127 に答える
7

考えられる解決策は 2 つあります。上記で提供したコードに最も近いものは次のとおりです。

newtype StateMonad e a = StateMonad (State -> Either e (a, State))

instance Monad (StateMonad e) where
    (StateMonad p) >>= k =
        StateMonad $ \s0 ->
            case p s0 of
                Right (val, s1) ->
                    let (StateMonad q) = k val
                     in q s1
                Left e -> Left e
    return a = StateMonad $ \s -> Right (a, s)

data State = State
    { log  :: String
    , a    :: Int
    }

もう 1 つの形式は、状態処理内でエラー処理を移動します。

newtype StateMonad e a = StateMonad (State -> (Either e a, State))

instance Monad (StateMonad e) where
    (StateMonad p) >>= k =
        StateMonad $ \s0 ->
            case p s0 of
                (Right val, s1) ->
                    let (StateMonad q) = k val
                     in q s1
                (Left e, s1) -> (Left e, s1)
    return a = StateMonad $ \s -> (Right a, s)

data State = State
    { log  :: String
    , a    :: Int
    }
于 2010-10-31T15:24:39.987 に答える
4

モナド変換子が必要です。mtlなどのモナド変換子ライブラリを使用すると、さまざまなモナドを作成して新しいバージョンを作成できます。mtlを使用して、次のように定義できます。

type StateMonad e a = StateT State (Either e) a

これにより、内の状態とエラー処理の両方にアクセスできるようになりますStateMonad

于 2010-10-31T15:29:18.390 に答える
4

ここで、Martin Grabmüller による Monad Transformers Step by Stepという論文に言及している人は誰も見ませんでした。

モナドの組み合わせについて学ぶのに非常に役立つことがわかりました。

于 2010-11-02T00:38:35.197 に答える
2

状態モナドを内部に持つErrorTモナド変換子をいつでも使用できます(またはその逆)。モナドに関するすべてのトランスフォーマーのセクションを見てください。

HTH、

于 2010-10-31T15:32:06.037 に答える