Take the 2-minute tour ×

Imagine we have a Haskell program which uses a library. The program provides a typeclass TC instance for a type T from one of its dependencies. In the next version of the same library, the library authors provided another instance of the typeclass TC for type T.

We want to use both of the typeclass instances. How can we do so?

P.S. newtype solution won't work. Both instances reside in libraries which we don't control.

P.P.S. I don't have an example of real code. It's a theoretical question. I just want to learn how type classes work with library composability.

share|improve this question

5 Answers 5

up vote 5 down vote accepted

The Haskell 2010 Report §4.3.2 states that


So it is not possible in standard Haskell.

I am not aware of any GHC extension that would allow you to do this in GHC.

This is (one?) reason why orphan instances (defining an instance in a different module from both the type and the typeclass) are generally considered a bad idea.

share|improve this answer

In general multiple type class instances for the same type isn't possible. However, if a type is defined in a different package, or an older version of the same package, ghc will consider it a different type. So you could in theory have foo-1.1 define Foo and instances for it, and foo-1.2 define Foo and instances for it, and use the two together.

However, in practice this wouldn't work well. Functions will only work with one type or the other. When you write a function that operates on a Foo, it will operate on only one particular Foo, not both of them. Essentially you have two completely separate, incontrovertible types. It would be awkward to use, completely separate from how awkward it will be to build.

share|improve this answer

I can say for sure that using Cabal you can only depend on a single version of the same library.

While it's possible for you to at least copy-paste the source code of the alternative version of the instance to your project, you're still only able to import one of them per module. If you'll import conflicting instances to a module, you'll bump into undecidable instances issue, for which you'll have no practical solution.

To tell you truth I can't imagine why one may want to have different instances of the same class for the same type emitted by the same library. It seems highly unpractical. Although my guess about what may help you with your situation is to have two typeclasses with according instances: one from the current version of the library and another - a renamed source code copy of the older one.

share|improve this answer

Linking with different versions of the same package on the dependency tree, is not possible by now because it leads to a dependency conflict.

But this will be possible in the future as stated in this GHC status update video, as long as they are used only one version in the same library I guess.

share|improve this answer

If you want better flexibility and composability, then reify the type classes as a record. RankNTypes may be necessary.

For example, here's how you could reify the Applicative type class

{-# LANGUAGE RankNTypes #-}

data ApplicativeInstance f = ApplicativeInstance
  { pure :: forall a. a -> f a
  , amap :: forall a b. (a -> b) -> f a -> f b

listApplicative = ApplicativeInstance
  { pure = \a -> [a]
  , amap = map
  , ap = \fs xs -> case fs of
      [] -> []
      f:fs' -> map f xs ++ ap cartesianListApplicative fs' xs

zipListApplicative = ApplicativeInstance
  { pure = \a -> [a]
  , amap = map
  , ap = \fs xs -> case (fs, xs) of
      ([], _) -> []
      (_, []) -> []
      (f:fs', x:xs') -> f x : ap zipListApplicative fs' xs'

Now, we gain the power of specifying which instance we want. However, we lose the power to implicitly choose an instance: selection must now be explicit.

ghci> ap listApplicative [(+1), (*3)] [1 .. 5]
ghci> ap zip
zip                 zipListApplicative  zipWith3
zip3                zipWith
ghci> ap zipListApplicative [(+1), (*3)] [1 .. 5]

See also: http://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existential-typeclass/

share|improve this answer

Your Answer


