Say I'm trying to define a new typeclass in Haskell, and among other things, it must have a + operation:
class Foo a where
(+) :: a -> a -> a
(In practice the typeclass Foo would have more stuff, but let me stop here to keep this minimal.)
Now, I want to make the basic "Integer" type an instance of Foo; and as far as the + operation goes, I just want to keep the usual addition, which is already defined. How do I do that?
Needless to say, the following makes no sense:
instance Foo Integer where
(+) x y = x+y
It loops forever when I ask Haskell to compute 2+3, but I suppose that's to be expected! I also tried putting nothing at all:
instance Foo Integer
This compiles, but then when I ask for 2+3 I get "No instance nor default method for class operation +". Again, it makes sense...
But how do we do that then?
I guess it's a general question "about the namespace", I mean, when two typeclasses use the same names, what happens? In my case, I get issues when trying to make a type (Integer) an instance of two typeclasses with such a name clash (Num and Foo).
From reading this question, I'm now afraid that what I'm asking for is just prohibited...
An instance of a class is an individual object which belongs to that class. In Haskell, the class system is (roughly speaking) a way to group similar types. (This is the reason we call them "type classes"). An instance of a class is an individual type which belongs to that class.
Type and data type refer to exactly the same concept. The Haskell keywords type and data are different, though: data allows you to introduce a new algebraic data type, while type just makes a type synonym. See the Haskell wiki for details.
Everything in Haskell has a type, so the compiler can reason quite a lot about your program before compiling it. Unlike Java or Pascal, Haskell has type inference.
To give a specific solution, something like this would work without having to deal with clashing with (+):
class Foo a where
(<+>) :: a -> a -> a
infixl 6 <+>
instance Foo Integer where
(<+>) = (+)
Now your class Foo has its own operator, and the fixity declaration means that (<+>) will be parsed the same way as (+).
If you really want to call your operation +
, and you want to define it in terms of the +
from Prelude, you can do it like this:
import Prelude (Integer, print)
import qualified Prelude ((+))
class Foo a where
(+) :: a -> a -> a
instance Foo Integer where
(+) x y = x Prelude.+ y
main = print (2 + 3 :: Integer)
This will output 5.
To prove that the definition of main
is really using our new +
operator and not the original one, we can change our definition of +
:
import Prelude (Integer, print)
import qualified Prelude ((+))
class Foo a where
(+) :: a -> a -> a
instance Foo Integer where
(+) x y = x Prelude.+ y Prelude.+ 1
main = print (2 + 3 :: Integer)
This will output 6.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With