2

状態が関与するモナドコードで命令型ループをエミュレートする小さなタスクがあり、IO がないはずです。タスクは条件付きでループを終了することであり、ここに私の試みがあります:

> execState (forever $ modify (+1) >>= \x -> guard $ x < 5 ) 1

したがって、ここでは 4 のようなものが得られると期待していますが、代わりに次の不可解なメッセージが表示されます。

<interactive>:1:43:
    No instance for (MonadPlus Data.Functor.Identity.Identity)
      arising from a use of `guard' at <interactive>:1:43-47
    Possible fix:
      add an instance declaration for
      (MonadPlus Data.Functor.Identity.Identity)
    In the first argument of `($)', namely `guard'
    In the expression: guard $ x < 5
    In the second argument of `(>>=)', namely `\ x -> guard $ x < 5'

全体はガードなしで問題なく動作しますが、何らかの理由で完全にガードが嫌いなようです。

UPD : 最後に、タイプのヒントを提供してくれた hammar のおかげで、実行できるようになりました。何も返さないにもかかわらず、5回実行されることはわかっています。これはクールですが、今のところどのように役立つかわかりません。

runStateT (forever $ do { modify (+1); x <- get; guard $ x < 5 } :: StateT Int Maybe Int) 1
4

2 に答える 2

2

エラーメッセージが伝えようとしているように、guard使用しているモナドはクラス型のインスタンスでなければなりませんMonadPlus

この例ではStateモナドを使用していますが、これは実際にはモナドStateT上のトランスフォーマーIdentityです。MonadPlusのインスタンスがありますStateTが、基礎となるモナドも a でなければならない必要がありますがMonadPlus、そうでIdentityはありません。

あなたの例では、次のようなものを試すことができます

> let loop = modify (+1) >> get >>= \x -> if x < 5 then loop else return x in execState loop 1
于 2011-04-04T17:36:20.337 に答える
1

すべてのモナドがガードをサポートしているわけではありません。MonadPlusのものだけ。Identityモナドを使用しているようです(おそらくexecStateの一部として)。警備員が失敗したときに何をしたいですか?

于 2011-04-04T17:32:21.897 に答える