Opened 3 years ago

Closed 2 years ago

Last modified 2 years ago

#6028 closed feature request (wontfix)

warning for cyclic unimplemented defaults

Reported by: lerkok Owned by:
Priority: normal Milestone:
Component: Compiler Version: 7.4.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Revisions:

Description

It's really nice how GHC warns when a class method is left out unimplemented. Alas, GHC does not warn if there's a default implementation that only works in case another method is defined.

Here's an example: The Num class allows either negate or '-' to be defined, providing default definitions for each in terms of the other. If a user leaves both undefined, then he gets himself a nice little tight-loop with no warnings. To break the cycle, the user should implement at least one of these. Thus, it would be really nice if GHC warned in such cases.

I'm guessing that GHC already has all the relevant information at hand when compiling an instance declaration, so I'm hoping it's not too much work to warn if there's such a cyclic dependency; just like it warns if the user leaves methods unimplemented.

Change History (4)

comment:1 Changed 3 years ago by lerkok

Along similar lines; it'd be really awesome if ghc computed that information, and printed it with :i, something like:

ghci> :i Num
minimal complete definition: +, *, abs, signum, fromInteger, and one of negate, -
....

comment:3 Changed 2 years ago by igloo

  • difficulty set to Unknown
  • Resolution set to wontfix
  • Status changed from new to closed

It's not quite that simple. The default implementations are:

negate x            = 0 - x
x - y               = x + negate y

so actually (-) is defined in terms of (+), not negate. For example, if we have:

data X = C
    deriving Show

instance Num X where
    _ + _ = C

then "-3 :: X" evaluates to C.

It also wouldn't work for shift:

x `shift`   i | i<0       = x `shiftR` (-i)
              | i>0       = x `shiftL` i
              | otherwise = x

x `shiftL`  i = x `shift`  i
x `shiftR`  i = x `shift`  (-i)

I'm not convinced that there are many instances where this would actually help, so I'm closing the ticket.

comment:4 Changed 2 years ago by lerkok

It is indeed possible to create scenarios where the "cycle" check would be fooled, like the one you showed above. But I don't think that's the "common case". I believe it remains a fact that a simply cycle check will catch a large number of practical instances of this problem. This is similar to the pattern-match completeness warning: While it may not be accurate 100%, it's so darn useful. And it's likely to be right more often than you'd think. In the 1% of cases where it's wrong, it's just a warning that the user can explicitly turn off via --noWarnUnimplementedCyclicMethod or some such.

Note: See TracTickets for help on using tickets.