Skip to content
  • Simon Peyton Jones's avatar
    Re-engineer the ambiguity test for user type signatures · 97db0edc
    Simon Peyton Jones authored
    Two main changes. First, re-engineer the ambiguity test.  Previously
    TcMType.checkAmbiguity used a rather syntactic test to detect some
    types that are certainly ambiguous.  But a much easier test is available,
    and it is used for inferred types in TcBinds. Namely
        <type> is ambiguous
    iff
       <type> `TcUnify.isSubType` <type>
    fails to hold, where "isSubType" means "is provably more polymorphic than".
    Example:
          C a => Int
    is ambiguous, because isSubType instantiates the (C a => Int)
    to (C alpha => Int) and then tries to deduce (C alpha) from (C a). This is
    Martin Sulzmann's definition of ambiguity.  (Defn 10 of "Understanding
    functional dependencies via constraint handling rules", JFP.)
    
    This change is neat, reduces code, and correctly rejects more programs.
    However is *is* just possible to have a useful program that would be
    rejected. For example
              class C a b
              f :: C Int b => Int -> Int
    Here 'f' would be rejected as having an ambiguous type. But it is
    just possible that, at a *call* site there might be an instance
    declaration  instance C Int b, which does not constrain 'b' at all.
    This is pretty strange -- why is 'b' overloaded at all? -- but it's
    possible, so I also added a flag -XAllowAmbiguousTypes that simply
    removes the ambiguity check.  Let's see if anyone cares.  Meanwhile
    the earlier error report will be useful for everyone else.
    
    A handful of regression tests had to be adjusted as a result, because
    they used ambiguous types, somewhat accidentally.
    
    Second, split TcMType (already too large) into two
    
      * TcMType: a low-level module dealing with monadic operations like
        zonking, creating new evidence variables, etc
    
      * TcValidity: a brand-new higher-level module dealing with
        validity checking for types: checkValidType, checkValidInstance,
        checkFamInstPats etc
    
    Apart from the fact that TcMType was too big, this allows TcValidity
    to import TcUnify(tcSubType) without causing a loop.
    97db0edc