• simonpj's avatar
    [project @ 2001-12-20 11:19:05 by simonpj] · 91c750cb
    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
HsDecls.lhs 28.2 KB