2016-07-21 9 views
0

私は、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" 

答えて

2

、あなたはevalTrace x >>= (\rx -> evalTrace y >>= (\ry -> Result() "Add\n" >> return (rx + ry)))にその

evalTrace (Add x y) = do 
    rx <- evalTrace x 
    ry <- evalTrace y 
    Result() "Add\n" >> return (rx + ry) 

desugarsを見ることができます。 ここでは、evalTrace xのログが最初に来て、次にevalTrace yのログ、次に実際の「追加」ログが来るはずです。 標準算術インタープリタの場合のように、式のポストオーダーツリートラバースを行っています。 あなたが探している:あなたはこのように元のコードを書いていたかもしれないので、a >> bdo {a;b} desugarsことlog = Result()

注意して

do 
    log "Add\n" 
    rx <- evalTrace x 
    ry <- evalTrace y 
    return (rx + ry) 

evalTrace (Add x y) = do 
    rx <- evalTrace x 
    ry <- evalTrace y 
    Result() "Add\n" 
    return (rx + ry) 
関連する問題