I see the problem now Sean. So in your example, is this correct:

"To use the machinery of 'Show', I have to add and instance Show T. But that would be an orphan instance. So there is no way for T to use show machinery without adding an orphan instance (aside from modifying a module not under your control)?"

Even newtype doesn't seem to help in your example. Show has all this machinery, but it seems completely unusable without adding an orphan instance or re-writing other people's modules. Is there no other way? This situation seems incredibly against re-usability, which I thought was Haskell's strength. Am I missing something?


On Mon, Aug 24, 2015 at 9:07 PM, Sean Leather <sean.leather@gmail.com> wrote:
On Mon, Aug 24, 2015 at 12:48 PM, Clinton Mead wrote:
After implementing the steps in (c), T is an instance of both C and C1, and both those instances define foo the same way. The only way I see a problem if is a module imports both C1 and C unqualified (they'll clash) but I see no reason to do that.

It's hard to respond with vague details. It may be in your case that what you say works. But this is not true in the general case. Consider the following simple example.

-- | A module out of your control
module A where
data T = T

-- | A module out of your control
module B where
class Show a where
  show :: a -> String
print :: Show a => a -> IO ()

-- | A module under your control
module C where
import A
import B
class Show' a where
  show' :: a -> String
instance Show' T where
  show' T = "T"

Now, you can use "show' T" anywhere you could use "show T" because the result of both functions is the same (monomorphic) type.

But you can't use "print T" from module B because you do not have an instance for Show of T. You could define a function "print' :: Show' a => a -> IO ()", but you are not using the functions that rely on Show (a.k.a. the "machinery" mentioned by Miguel). Thus, you lose out on the common functionality that presumably exists for Show.

Regards,
Sean