I am trying to build my own calculator in Haskell with class declaration.
Firstly, I was trying to implement the addition, but here I got the error:
Couldn't match expected type 'Exp -> Double' with actual type 'Exp'
data Exp = Number Double | Add Exp Exp
class Calc a where
calculate :: a -> a -> Double
instance Calc Exp where
calculate (Add a b) = a b
What do I have to change?
CodePudding user response:
You don't really need, nor would I recommend, a class here. Just define an ordinary function that handles each of the data constructors separately. (Use a class only if you expect to have multiple types that can be used with calculate
.)
In either case, calculate
takes a single argument, as your type represents an entire expression, operands and operator together.
calculate :: Exp -> Double
calculate (Number n) = ...
calculate (Add a b) = ...
Keep in mind that a
and b
are values of type Exp
, not numbers (i.e., types with a Num
instance) that you can add directly. (This suggests you need to recursively calculate the value of a
and b
before you can actually perform addition.)
Some test cases for you to consider:
n1 = Number 2.0
n2 = Add (Number 3.0) (4.0))
n3 = Add n1 n2
map calculate [n1, n2, n3] == [2.0, 7.0, 9.0]
CodePudding user response:
As suggested by chepner, your calculate
function need only take a single argument. You also need to account for the possibility that each Exp
value maybe be a Number
and handle that in the function.
Since a
and b
are Exp
values and not Num
instances, you will need to apple calculate
to them.
data Exp = Number Double | Add Exp Exp
class Calc a where
calculate :: a -> Double
instance Calc Exp where
calculate (Number n) = n
calculate (Add a b) = a' b'
where a' = ...
where b' = ...
But you might consider making Exp an instance of Num
. The below is incomplete as it doesn't account for actual expressions except for
, but it might hint at what's possible.
instance Num Exp where
( ) (Number n1) (Number n2) = Number (n1 n2)
( ) (Add a b) c@(Number _) = a b c
( ) a@(Number _) (Add b c) = a b c
( ) (Add a b) (Add c d) = a b c d
(*) (Number n1) (Number n2) = Number (n1 * n2)
abs (Number n) = Number (abs n)
negate (Number n) = Number (negate n)
signum (Number n) = Number (signum n)
fromInteger n = Number (fromIntegral n)
ghci> case Add (Number 5) (Number 6) Number 7 of { Number n -> n }
18.0