Multiple instances

From HaskellWiki
Revision as of 15:43, 20 January 2009 by Lemming (talk | contribs) (Monoid)
Jump to navigation Jump to search

Question

I like to define multiple type class instances for the same pair of class and type. Sometimes I also need two instances where the order of type parameters is different. E.g. I want to define two Functor instances for a pair: One instance where the first member is mapped and another instance where the second member is mapped. How is it possible?


Answer

You can achieve the first goal if you keep class and type definitions in other modules than the instance declarations. These instances are then called orphan instances. However you won't be lucky with this solution, since you must ensure, that two modules with conflicting instances declarations are never imported together, since instance declarations are automatically imported and cannot be hidden. Even more also modules which import conflicting modules only indirectly conflict itself. The second problem cannot be solved with this approach, too.

Thus multiple instances should be avoided, and a safe way to do this is to avoid orphan instances. You can achieve this by wrapping the type in a newtype and lift all required instances to that new type. If you do not fear language extensions you can simplify this task considerably using the GeneralizedNewtypeDeriving feature. The custom instance can be defined for the class/newtype pair and it is not orphan, if it is defined where newtype is introduced. Using newtype you can also change the order of type parameters or give type parameters a fixed type.

Example: There are so many types and operations that exhibit a monoid structure, but it would not be useful to call all the operations mempty and mappend. It is however useful to call them via the Monoid interface sometimes, e.g. in the Writer monad. Thus the module Data.Monoid provides several newtype wrappers for common monoids.


See also