I want to make the data type Moneda
a instance of the Semigroup, and implement the associative operation as +
. I'm having difficulties understanding it properly.
The working solution I found, is the following:
data Moneda a = RON Double | EUR Double deriving (Show)
instance Num a => Num (Moneda a) where
(RON x) + (RON y) = RON (x + y)
(RON x) + (RON y) = RON (x + y)
instance Semigroup (Moneda a) where
(<>) = (+)
I couldn't understand why exactly the below aproach is failing and how it's possible to make it work without making Moneda
a Num
instance.
data Moneda a = RON a | EUR a deriving (Show)
instance Semigroup (Moneda a) where
(<>) (RON a) (RON b) = (RON a+b) -- fails, please see error below
vs
(<>) (RON a) (RON b) = (RON a) -- works but doesn't help me because I need the a+b sum
-- cannot construct the infinite type: a ~ Moneda a
-- In the second argument of `(+)', namely `b'
The error you're getting is because you try to add a value of type
Moneda a
to a value of typea
in your implementation of(<>)
. That is you wrote(RON a+b)
which parses as(RON a) + b
(because function/constructor application binds stronger than addition). You probably meant to writeRON (a + b)
as in:But that won't work either as it requires addition to be defined on the type to which you apply
Moneda
. So, for your definition to make sense you will need to constrain the instantiation of the type argumenta
to types inNum
:For example:
Note that this definition of
(<>)
is only partial. It does not account for adding values built withRON
to values built withEUR
:So, you still have to write code that deals with those cases.