This is a calculator that only sums numbers:
module Data.Calculator where
data Expr = Plus Expr Expr | Value Int
evaluate :: Expr -> Int
evaluate (Value a) = a
evaluate (Plus (Value a) (Value b)) = a + b
evaluate (Plus (Plus left right) (Value b)) = (evaluate left) + (evaluate right) + b
evaluate (Plus (Value a) (Plus left right)) = a + (evaluate left) + (evaluate right)
evaluate (Plus a@(Plus left right) b@(Plus left' right')) = (evaluate a) + (evaluate b)
The evaluate function seems way to verbose. Ideally I'd like to define a typeclass both operators and then define Plus as an instance of an operator, something like this:
class BinaryOp a where
apply :: a -> a -> Expr
instance BinaryOp Plus where
apply x y = x + y
But this obviously does not work because the type a that BinaryOp is defined with is an operator and not an operand.
How do I do this?