简体   繁体   中英

Make a parametrized data type instance of Semigroup

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 type a 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 write RON (a + b) as in:

data Moneda a = RON a | EUR a deriving (Show)

instance Semigroup (Moneda a) where
  (<>) (RON a) (RON b) = RON (a + b)

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 argument a to types in Num :

data Moneda a = RON a | EUR a deriving (Show)

instance Num a => Semigroup (Moneda a) where
  RON a <> RON b = RON (a + b)
  EUR a <> EUR b = EUR (a + b)

For example:

> RON 2 <> RON 3
RON 5

Note that this definition of (<>) is only partial. It does not account for adding values built with RON to values built with EUR :

> RON 5 <> EUR 7
*** Exception: Main.hs:(4,3)-(5,30): Non-exhaustive patterns in function <>

So, you still have to write code that deals with those cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM