Wish list: expanded defaulting, dependent types, reflection
Sat, 29 Sep 2001 17:44:41 -0700
At 2001-09-29 17:07, Mike Gunter wrote:
>class Add a b c | a b -> c where add :: a -> b -> c
>instance Add Integer Integer Integer where add = (+)
>pt1 = (3::Integer) `add` (4::Integer) -- Works fine,
>--ft2 = (5::Integer) `add` 6 -- Fails
OK, you're running across a fundamental design shortcoming in GHC's
instance overlap calculation. What you want to do is this:
class Add a b c | a b -> c where add :: a -> b -> c
instance (Integral a,Integral b) => Add a b Integer where
add a b = (toInteger a) + (toInteger b)
pt1 = (3::Integer) `add` (4::Integer)
ft2 = (5::Integer) `add` 6
So far so good. The trouble comes when you want to add your own type:
instance (Integral b) => Add MyInt b MyInt where
add (MkMyInt a) b = MkMyInt (a + (toInteger b))
Provided you don't declare 'instance Integral MyInt', the two instances
will not de facto overlap. But GHC will complain that they do, because
GHC's understanding of overlapping instances is excessively conservative.
This is currently top of my list of GHC problems.
GHC annoyingly ignores the class contexts and simply sees this:
Add a b _
Add MyInt b _
...from which it deduces that the instances overlap.
So can't you just switch on -fallow-overlapping-instances and not worry
about it? Ordinarily, yes, but for some reason that doesn't work when you
have a dependent parameter in your class. It's like it's a different
piece of code doing the checking, or something. I've entered a bug for
108032>. I don't know if this has been fixed in 5.02.
Ashley Yakeley, Seattle WA