-
simonpj authored
--------------------------------------------- More type system extensions (for John Hughes) --------------------------------------------- 1. Added a brand-new extension that lets you derive ARBITRARY CLASSES for newtypes. Thus newtype Age = Age Int deriving( Eq, Ord, Shape, Ix ) The idea is that the dictionary for the user-defined class Shape Age is *identical* to that for Shape Int, so there is really no deriving work to do. This saves you writing the very tiresome instance decl: instance Shape Age where shape_op1 (Age x) = shape_op1 x shape_op2 (Age x1) (Age x2) = shape_op2 x1 x2 ...etc... It's more efficient, too, becuase the Shape Age dictionary really will be identical to the Shape Int dictionary. There's an exception for Read and Show, because the derived instance *isn't* the same. There is a complication where higher order stuff is involved. Here is the example John gave: class StateMonad s m | m -> s where ... newtype Parser tok m a = Parser (State [tok] (Failure m) a) deriving( Monad, StateMonad ) Then we want the derived instance decls to be instance Monad (State [tok] (Failure m)) => Monad (Parser tok m) instance StateMonad [tok] (State [tok] (Failure m)) => StateMonad [tok] (Parser tok m) John is writing up manual entry for all of this, but this commit implements it. I think. 2. Added -fallow-incoherent-instances, and documented it. The idea is that sometimes GHC is over-protective about not committing to a particular instance, and the programmer may want to say "commit anyway". Here's the example: class Sat a where dict :: a data EqD a = EqD {eq :: a->a->Bool} instance Sat (EqD a) => Eq a where (==) = eq dict instance Sat (EqD Integer) where dict = EqD{eq=(==)} instance Eq a => Sat (EqD a) where dict = EqD{eq=(==)} class Collection c cxt | c -> cxt where empty :: Sat (cxt a) => c a single :: Sat (cxt a) => a -> c a union :: Sat (cxt a) => c a -> c a -> c a member :: Sat (cxt a) => a -> c a -> Bool instance Collection [] EqD where empty = [] single x = [x] union = (++) member = elem It's an updated attempt to model "Restricted Data Types", if you remember my Haskell workshop paper. In the end, though, GHC rejects the program (even with fallow-overlapping-instances and fallow-undecideable-instances), because there's more than one way to construct the Eq instance needed by elem. Yet all the ways are equivalent! So GHC is being a bit over-protective of me, really: I know what I'm doing and I would LIKE it to pick an arbitrary one. Maybe a flag fallow-incoherent-instances would be a useful thing to add?
91c750cb