
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