[Haskell-cafe] Consequences of newtype deriving implementation w.r.t. base classes

2007-03-13 Thread Twan van Laarhoven
I just noticed some unexpected consequences of the way newtype deriving 
is implemented in GHC. Because the dictionary of the underlying type is 
reused, so are base classes. This message is a literate Haskell program 
illustrating the problem.


 {-# OPTIONS_GHC -fglasgow-exts #-}

This problem comes up when an instance method calls a method of a base 
class. Consider the following useless example:


 class Show a = Show2 a where
   show2 :: a - String
show2 = show

 instance Show2 Int

Now consider a type deriving Show2, but having a different 
implementation of Show (also derived).


 newtype Meter = Meter Int
deriving (Eq, Show, Show2)

Now, for show2 the derived Show instance (which also shows the 
constructor name) is *not* used, instead the Show Int instance is used:


]  show2 (Meter 1)
] 1
]  show  (Meter 1)
] Meter 1

This is quite unexpected, unless you consider what is going on behind 
the scenes. Even more confusingly, GHC requires that there is a Show 
instance for Meters, even if it will not be used!


]No instance for (Show Meter)
]  arising from the superclasses of an instance declaration at ...
]Probable fix: add an instance declaration for (Show Meter)
]In the instance declaration for `Show2 Meter'

This problem can come up whenever a class instance uses a function from 
a base class. Right now this not likely happen, but it will become more 
common if the standard classes are split up:


 class Additive a where
   add :: a - a - a
 class Additive a = Subtractive a where
   neg :: a - a
   sub :: a - a - a
   sub x y = add x (neg y) -- calls base class function add

 class Functor m = Monad' m where
   return' :: a - m a
   join' :: m (m a) - m a
   join' x = bind' x id
   bind' :: m a - (a - m b) - m b
   bind' ma k = join' (fmap k ma) -- calls base class function fmap

As a solution I would suggest that newtype deriving a class instance is 
only allowed if all base classes instances are also derived using 
newtype deriving. This presents problems for Show and Read, because they 
cannot be derived in that way. It will, however, catch problems with 
most other classes.


Twan van Laarhoven
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


RE: [Haskell-cafe] Consequences of newtype deriving implementation w.r.t. base classes

2007-03-13 Thread Simon Peyton-Jones
| I just noticed some unexpected consequences of the way newtype deriving
| is implemented in GHC. Because the dictionary of the underlying type is
| reused, so are base classes. This message is a literate Haskell program
| illustrating the problem.

Excellent point.

| As a solution I would suggest that newtype deriving a class instance is
| only allowed if all base classes instances are also derived using
| newtype deriving. This presents problems for Show and Read, because they
| cannot be derived in that way. It will, however, catch problems with
| most other classes.

Yes, I think you are right.  I'll make a Trac bug report for it; but I think 
I'll fix it in the HEAD only.

S
___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe