Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using plus operation for non-parameterized datatypes

Tags:

haskell

I have a simple class that includes an "add" operation

class (Eq a, Show a, Read a) => Group a where 
  add :: a -> a -> a

I created a new datatype called "Z5" with one constructor parameter, namly an int value:

data Z5 = Z5 Int deriving (Eq, Read, Show)   

The instantiation of the datatype looks like this:

instance Group (Z5) where
  add x y = x+y

The thing is that I get the error message:

 No instance for (Num Z5) arising from a use of `+'
 Possible fix: add an instance declaration for (Num Z5)

I tried it with

instance (Num Z5) => Group (Z5) where
 add x y = x+y

but then the error message is:

 Non type-variable argument in the constraint: Num Z5
 (Use -XFlexibleContexts to permit this)
 In the context: (Num Z5)
 While checking an instance declaration
 In the instance declaration for `Group (Z5)'
like image 455
enne87 Avatar asked Mar 10 '26 14:03

enne87


2 Answers

This error is pretty straight forward: No instance for (Num Z5) arising from a use of `+'. You need a 'Num' instance for Z5. You have several options:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Z5 = Z5 Int deriving (Eq, Read, Show, Num)   

This creates a Num instance for your type identical to that of Int. Or, you can write the instance manually, if you don't want it the be the same as the one for Num.

instance Num Z5 where
     (Z5 a) + (Z5 b) = Z5 (a + b + 5) -- you can do whatever you like here

Writing the constraint C T where C is a typeclass and T is a monomorphic type is always pointless; this will either be true in which case you don't need to write the constraint, or it will be false in which case it will not compile.

More generally, any instance of Num is a mathematical group, so you can write:

-- This newtype is defined in Data.Monoid
newtype Sum a = Sum a
instance Num a => Group (Sum a) where 
  add (Sum a) (Sum b) = Sum (a + b) 
  identity = Sum 0
  invert (Sum x) = Sum (-x)

Then you can do things like:

>add ((Sum 4) :: Sum Z5) ((Sum 5) :: Sum Z5)
Sum {getSum = Z5 9}
like image 195
user2407038 Avatar answered Mar 12 '26 06:03

user2407038


Did you mean to use + for your Z5 type directly in your original code or did you perhaps mean to write

instance Group Z5 where
  add (Z5 x) (Z5 y) = Z5 (x+y)

The + operation only works for numbers (i.e. instances of the Num type-class) so you can't automatically use it for custom data types such as your Z5.

like image 38
shang Avatar answered Mar 12 '26 05:03

shang



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!