Monday, July 25, 2016

Haskell: How (not) to Overload Type Classes

After studying haskell as a hobby for some time now, I'm still "thinking OOP"... In particular I still don't find myself comfortable with Type Classes.

Extending Type Classes

Every time I use them I "feel" the need to write a Type Class that extends another one (as if they where c++ classes). But if you want to extend a Type Class you just need a plain function. Like in:
class T1 a where
    m1 :: a -> Int

doubleM1 :: (T1 a) => a -> Int
doubleM1 x = 2 * m1 x 
Of course if you can alter the Type Class definition itself you can add doubleM1' to the Type Class itself like in:
class T1 a where
    m1 :: a -> Int
    doubleM1' :: a -> Int
    doubleM1' x = 2 * m1 x
This second form is more powerful because you can write different implementations for different instances, if so you desire. That is not always a good thing, see:
instance T1 Double where
    doubleM1' x = 3 * m1 x
    m1 = round

My Question

Suppose I have two Type Classes (e.g. they are not not my own Type Classes i.e. I can't modify them)
class T1 a where
    m1 :: a -> Int

class T2 a where
    m2 :: a -> Int
Can I write a Type Class member (or a plain function) that accepts any instance of T1 or T2 and gives back an Int? For instance like in:
class T a where
    m ::  => a -> Int

instance T AnyTypeThatHasAnInstanceForT1 where
    m = m1

instance T AnyTypeThatHasAnInstanceForT2 where
    m = m2
I think my OOP trained brain wants to use overloading in order to avoid writing all my instances twice. What is an idiomatic haskell way of solving such problem?