mappend
概要: Writer モナドを使用しているときに、状態を失うことなくの 2 つの異なるバージョンを切り替えられるようにしたいと考えています。
いくつかの状態を追跡するために、2 つのブール値フラグを使用します。
data Flags = F Bool Bool
Monoid
次に、フラグを組み合わせる方法が異なる2 つのインスタンスを定義しmappend
ます。
newtype XFlags = XF Flags
instance Monoid XFlags where
mempty = XF (F True False)
(XF (F s0 c0)) `mappend` (XF (F s1 c1)) = XF (F (s0 && s1)
(c0 || c1 || not (s0 || s1)))
newtype SFlags = SF Flags
instance Monoid SFlags where
mempty = SF (F True False)
(SF (F s0 c0)) `mappend` (SF (F s1 c1)) = SF (F (s0 && s1) (c0 || c1))
これで、異なるフラグ処理を持つ 2 つの Writer モナドを持つことができます:
type XInt = WriterT XFlags Identity Int
type SInt = WriterT SFlags Identity Int
これで、次のような操作を実行できます。
xplus :: XInt -> XInt -> XInt
xplus = liftM2 (+)
splus :: SInt -> SInt -> SInt
splus = liftM2 (+)
次のような式を作成したいと思います。
foo = splus (return 1) (xplus (return 2) (return 3))
そのためには、フラグを失うことなく、できれば ( を使用してrunWriter
) モナドをアンラップすることなく、2 つの間で変換できる必要があります。この部分は私が把握していません。モナドトランスフォーマーを使用してライターをネストできるように少し見えますが、ここで直接適用できるかどうかはわかりません。このようなものを実装するための最良の方法について、いくつかのガイダンスをいただければ幸いです。