至少我认为这是怎么回事。失败处理在错误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