
On Tue, 13 Dec 2011 21:40:13 +0000
Peter Hall
It seems to work, but I could do with some feedback, as it isn't quite satisfactory. It feels like I should be able to remove some of the duplicated code in the eval function, and also in evalIntExpr and evalBoolExpr, which are identical except for having Left and Right reversed.
I'm also relatively new at this. My first thought was "eval should be
pure". After going back and reading the description, and thinking
about why you were running in the Maybe monad, I figured out what was
going on.
Anyway, here's my take on it. I've left your code quoted, added the
new code in unquoted, and deleted what it replaced.
-------- Arithmetic.hs module Arithmetic where
import Data.Maybe data Expr = I Int
| B Bool
| Add Expr Expr
| Mult Expr Expr
| Eq Expr Expr eval :: Expr -> Maybe (Either Bool Int)
eval (B b) = return $ Left b
eval (I i) = return $ Right i eval (Mult e1 e2) = applyIntOp Right (*) e1 e2
eval (Add e1 e2) = applyIntOp Right (+) e1 e2
eval (Eq e1 e2) = applyIntOp Left (==) e1 e2
applyIntOp :: (t -> b) -> (Int -> Int -> t) -> Expr -> Expr -> Maybe b
applyIntOp const func e1 e2 = do
a1 <- evalIntExpr e1
a2 <- evalIntExpr e2
return $ const $ func a1 a2 evalIntExpr :: Expr -> Maybe Int
evalIntExpr e = eval e >>= (either (\_ -> Nothing) Just) evalBoolExpr :: Expr -> Maybe Bool
evalBoolExpr e = eval e >>= (either Just (\_ -> Nothing)) ------- Main.hs module Main (
main
) where import Arithmetic
import Data.Maybe
import Data.Either test :: Expr
test = Eq
(Mult
(Add
(I 1)
(I 2)
)
(I 5)
)
(I 15) main :: IO ()
main = do
putStrLn $ case eval test of
Nothing -> "Invalid expression"
Just (Left x) -> show x
Just (Right x) -> show x