私は、HaskellでMonadsとそのバインド操作をよりよく理解するためにいくつかの練習をしていました。そのために、途中で実行された操作を追跡するロガーを作成することにしました。モナドインスタンスとして有するロガーでのバインド操作の出力順が正しくないMonad
data Log e a = Error e | Result a String deriving (Show)
:シナリオでロガーを試験するために
instance Monad (Log e) where
(>>=) (Error e) _ = Error e
(>>=) (Result x log) f = case f x of
Error e -> Error e
Result r log' -> Result r (log ++ log')
return x = Result x ""
は、私は単純な算術演算を表すデータ型を書いたので、私は、次のデータ型を作成しました。データ型は以下のようになります。
除算が存在するので、Logデータ型のErrorコンストラクタを使用してゼロ除算を処理したいと考えています。
のeval関数式を評価し、次のようになります途中でトレース:
evalTrace :: Exp -> Log String Int
最終結果がどのように見えるかのクエリ:ここ
Main> evalTrace (Add (Lit 1) (Mul (Lit 2) (Lit 3)))
(7, "Add\nLit\nMul\nLit\nLit\n")
は私が書いたものですfar:
evalTrace :: Exp -> Log String Int
evalTrace (Lit x) = Result() "Lit\n" >> return x
evalTrace (Add x y) = do
rx <- evalTrace x
ry <- evalTrace y
Result() "Add\n" >> return (rx + ry)
evalTrace (Mul x y) = do
rx <- evalTrace x
ry <- evalTrace y
Result() "Mul\n" >> return (rx * ry)
evalTrace (Div x y) = do
rx <- evalTrace x
ry <- evalTrace y
if ry == 0
then (Error "division by zero")
else Result() "Div\n" >> return (div rx ry)
算術演算は正しく処理されますが、年齢は順不同で印刷されます。私は確かにここでは何かが分からないと思うが、問題を解決できないようだ。
クエリ:ログメッセージが実際に順番に印刷され
Main> evalTrace (Add (Lit 1) (Mul (Lit 2) (Lit 3)))
Result 7 "Lit\nLit\nLit\nMul\nAdd\n"