At least I think that’s what’s going on.
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))
But, when eval fails, I get an error in IO, without the “Error: ” string appended.
Which version of
baseare you using?failis no longer defined to return aLeftin the latest version of theEither emonad, instead it uses the default definition (which callserror, which throws an exception that can only be caught in IO).I don’t know why this changed.