至少我認爲這是怎麼回事。失敗處理在錯誤monad
Main.hs:
module Main (
main
) where
import Arithmetic
import Data.Maybe
import Data.Either
import Control.Monad.Error
testExpr :: Expr Float
testExpr =
(MultExpr "*"
(AddExpr "XXX"
(NumExpr 1)
(AddExpr "-"
(NumExpr 24)
(NumExpr 21)
)
)
(NumExpr 5)
)
main :: IO()
main = do
putStrLn $ case eval testExpr of
Left msg -> "Error: " ++ msg
Right result -> show result
Arithmetic.hs:
{-# LANGUAGE GADTs #-}
module Arithmetic where
type Op = String
data Expr a where
NumExpr :: Float -> Expr Float
AddExpr :: Op -> Expr Float -> Expr Float -> Expr Float
MultExpr :: Op -> Expr Float -> Expr Float -> Expr Float
eval :: (Monad m) => Expr Float -> m Float
eval (NumExpr n) = return n
eval (AddExpr "+" e1 e2) = evalBin (+) e1 e2
eval (AddExpr "-" e1 e2) = evalBin (-) e1 e2
eval (AddExpr "%" e1 e2) = evalBin (%) e1 e2
eval (AddExpr _ _ _) = fail "Invalid operator. Expected +, - or %"
eval (MultExpr "*" e1 e2) = evalBin (*) e1 e2
eval (MultExpr "/" e1 e2) = evalBin (/) e1 e2
eval (MultExpr _ _ _) = fail "Invalid operator. Expected * or /"
evalBin :: (Monad m) => (Float -> Float -> Float) -> Expr Float -> Expr Float -> m Float
evalBin op e1 e2 = do
v1 <- eval e1
v2 <- eval e2
return $ op v1 v2
infixl 6 %
(%) :: Float -> Float -> Float
a % b = a - b * (fromIntegral $ floor (a/b))
但是,當eval
失敗,我得到IO錯誤,沒有 「錯誤:」 字符串追加。
這不可能與你在這裏介紹的代碼; 'eval testExpr'在'Either' monad中評估,並且永遠不會接近'IO'。你遺漏的代碼必須有錯誤;例如,您的評估代碼的另一部分可能會直接或間接地調用'error',這會冒充IO異常。 – ehird 2011-12-18 18:49:10
謝謝,我已經用完整代碼更新了帖子 – 2011-12-18 19:03:54
原來的代碼中可以看到問題,我只是錯過了;我已經發布了一個修復:) – ehird 2011-12-18 19:14:40