7

失敗する可能性のある計算のモナドがあり、ログを記録します。

f1 :: WriterT [String] (Either String) a

失敗しない関数がありますが、ログを記録します。

f2 :: Writer [String] b

f2からのログを使用してf1のライターモナドを更新し、f2計算の出力をキャプチャするための最良の方法は何ですか?現在、私はこれを行っています:

f2result <- (\(r,l) -> do {tell l; return r}) (runWriter f2)

私はリフトを使用して内部モナドを別の計算で更新しているので、ライターとどちらかのモナドを切り替えても問題は解決しません。

4

2 に答える 2

4

を定義した場合f2、最も簡単なアプローチは、f2次のように定義されるようにリファクタリングすることです。

 f2 :: Monad m => WriterT [String] m b

Writer w bとして定義されているので、これはそれほど難しいことではWriterT w Identity bありIdentityません。モナドは何も与えません。

そうすれば、を実行するだけでそれらを連鎖させることができますf1 >> f2

再定義できない場合はf2、いつでも適切な署名を使用して独自の定義を作成できます。

 f2' :: Monad m => WriterT [String] m b
 f2' = WriterT . return $ runWriter f2

そして、あなたがたくさんのf2ラップをしているなら、あなたはいつでもあなたのためにそれらをラップする関数を定義することができます

 wrap :: Monad m => Writer w b -> WriterT w m b
 wrap = WriterT . return . runWriter

だからあなたはすることができますf1 >> wrap f2a >> wrap f2b >> wrap f2c ...

于 2012-03-14T14:50:17.250 に答える
4

暴れん坊の答えのフォローアップとして、代わりf2 に任意のリファクタリングを行うことができますMonadWriter

f2 :: MonadWriter [String] m => m a

定義を変更できない場合は、ランピオンと同じようにラップできます。

f2' :: MonadWriter [String] m => m a
f2' = do let (a,w) = runWriter f2
         tell w
         return a

このGHCプラグマを要求するための[String]引数:MonadWriter

{-# LANGUAGE FlexibleContexts #-}

いつものように、プラグマはモジュールの上部に配置されます。

コメントで、ランピオンはこの設定で関数をラップするバージョンを提供しました:

wrap :: MonadWriter w m => Writer w b -> m b
wrap = uncurry (<<) . (return *** tell) . runWriter 
  where (<<) = flip (>>)
于 2012-03-14T15:52:52.097 に答える