4
votes

While trying to understand instances in Haskell I made this example. The Integer part works well but it does not work for the Float instance. I think it is better to make a single instance of the type Num (so that square works on all Num). I suppose I have to add Num as a constraint to my class declaration but I couldn't figure out what the instance would look like. As I understand it, the constraint on the class forces any instances to be of that type (according to the constraint).

class Square a where
    area :: a -> a

instance Square Integer where
    area a = a*a

instance Square Float where
    area a = a*a
1
That Square Float instance should work just fine. What problem a you experiencing with it?leftaroundabout
The above code should work fine for Float. You should just call, for example area 10.0::Float to remove ambiguity.Yogesh Sajanikar

1 Answers

10
votes

I think it is better to make a single instance of the type Num...

Not really, unless you want to define that class only for Num types (and then you don't need a class at all, just make it area :: Num a => a->a as a top-level function).

Here's the way to make such a generic instance:

instance (Num a) => Square a where
  area a = a*a

This is not Haskell98, but it does work with the widely used -XFlexibleInstances and -XUndecidableInstances extensions.

Problem: if you then also want to add, say,

instance Square String where
  area str = concat $ replicate (length str) str

you have two overlapping instances. And that's a problem: in general, the compiler can't decide which of two such instances is the right one. Again GHC has extensions to make the best guess (-XOverlappingInstances and -XIncoherentInstances), but unlike Flexible/UndecidableInstances these are generally avoided.

Therefore I would recommend making individual instances Square Int, Square Integer, Square Double. They're not, like, hard to write, are they?