Classes like Haskell are based on first-order logical resolution. The type type restriction for a type variable is a predicate (you may have seen error messages indicating this if you ever tried to use the type class name where the type name is required) in this logical system.
Haskell requires a unique solution for each pair (Predicate, Type) in the entire program, so you cannot create, for example, two different instances of Functor by Int. The standard way to do this, for example, in the Monoid class for numeric types, which can provide summation or a product depending on how you define the monoid operator you want to use, is to provide newtype wrappers over the specific type you want the class to have different instances for.
So, for Monoid we have newtype Sum a = Sum { getSum :: a } and instance Num a => Monoid (Sum a) for the sum of the monoid and newtype Product a = Product { getProduct :: a } and instance Num a => Monoid (Product a) for the product monoid.
Note that since type only creates an alias for the type, this is not enough to provide multiple instances of the class for the type. The newtype declaration is similar to type in the sense that it does not create an additional runtime structure for the new type, but unlike type , a new type is created in it, not a type alias.
source share