[Haskell-beginners] How to remove some duplication from this code?
Peter Hall
peter.hall at memorphic.com
Tue Dec 13 22:40:13 CET 2011
I'm following this article about GADTs
[http://en.wikibooks.org/wiki/Haskell/GADT] and it suggests, as an
exercise, to handle invalid trees at runtime, without GADTs, when
evaluating a simple arithmetic syntax tree. My attempt is below.
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.
Thanks,
Peter
-------- 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) = do
a1 <- evalIntExpr e1
a2 <- evalIntExpr e2
return $ Right $ a1 * a2
eval (Add e1 e2) = do
a1 <- evalIntExpr e1
a2 <- evalIntExpr e2
return $ Right $ a1 + a2
eval (Eq e1 e2) = do
a1 <- evalIntExpr e1
a2 <- evalIntExpr e2
return $ Left $ a1 == a2
evalIntExpr :: Expr -> Maybe Int
evalIntExpr e = eval e >>= unwrap
where
unwrap (Right x) = Just x
unwrap (Left x) = Nothing
evalBoolExpr :: Expr -> Maybe Bool
evalBoolExpr e = eval e >>= unwrap
where
unwrap (Left x) = Just x
unwrap (Right x) = 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
More information about the Beginners
mailing list