Bug in context reduction with overlapping instances

Jeffrey R Lewis jeff@galconn.com
Thu, 20 Dec 2001 12:54:01 -0800


On Monday 17 December 2001 09:21 pm, John Hughes wrote:
> Here's a small program defining a collection class:
> ------------------
> class Sat a where
>   dict :: a
>
> data EqD a = EqD {eq :: a->a->Bool}
>
> instance Sat (EqD a) => Eq a where
>   (==) = eq dict
>
> 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
> ------------------
> Loading this program with overlapping instances turned on produces the
> error message:
>
> Type checking
> ERROR "C:\windows\Skrivbord\HugsBug.hs":24 - Cannot justify constraints in
> instance member binding *** Expression    : member
> *** Type          : (Collection [] EqD, Sat (EqD a)) => a -> [a] -> Bool
> *** Given context : (Collection [] EqD, Sat (EqD a))
> *** Constraints   : Eq a
>
> Very strange, given the instance declaration
>
>     instance Sat (EqD a) => Eq a
>
> The behaviour is the same in the February and December 2001 versions.

This is not a bug, but a misunderstood feature ;-)  There's two different 
ways to derive a Sat instance for EqD Integer, thus two ways to derive the Eq 
instance needed by `member', and hugs can't prove that the two instances will 
always be the same, so it bails out.

I've followed the suggestion posed to GHC on this same matter, and added a 
flag allowing potentially inconsistent overlaps for users who know what they 
are doing.  The new flag `+O' is the same as '+o', except that it allows 
potentially inconsistent overlaps.

--Jeff