Opened 12 months ago

Last modified 5 months ago

#9267 new bug

Lack of type information in GHC error messages when the liberage coverage condition is unsatisfied

Reported by: danilo2 Owned by:
Priority: high Milestone: 7.12.1
Component: Compiler Version: 7.8.2
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Incorrect warning at compile-time Test Case:
Blocked By: Blocking:
Related Tickets: Differential Revisions:

Description (last modified by danilo2)

Hello! The problem is not a bug related to proper code execution, but it affects the development in such way, we can treat it as a bug.

Lets think about such simple code (it can be further simplified of course):

{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}

data UnsafeBase base err val = Value val
                             | Error err
                             | Other (base val)
                             deriving (Show, Eq)

class MagicMerge m1 m2 | m1 -> m2 where
    magicMerge :: m1 a -> m2 a


instance MagicMerge (UnsafeBase (UnsafeBase base err) err) (UnsafeBase base err) where
    magicMerge ma = case ma of
        Value a -> Value a
        Error e -> Error e
        Other o -> o

instance MagicMerge (UnsafeBase (UnsafeBase base err1) err2) (UnsafeBase dstBase err1) where
    magicMerge (ma :: UnsafeBase (UnsafeBase base err1) err2 a) = case ma of
        Value a -> Value a
        Error e -> Other $ magicMerge (Error e :: UnsafeBase base err2 a)
        Other o -> case o of
            Value a  -> Other $ magicMerge (Value a  :: UnsafeBase base err2 a)
            Error e  -> Error e
            Other o' -> Other $ magicMerge (Other o' :: UnsafeBase base err2 a)


main = print "help me world!"

When trying to compile it using GHC-7.8, we get following error message:

  Illegal instance declaration for
    MagicMerge
       (UnsafeBase (UnsafeBase base err1) err2) (UnsafeBase dstBase err1)
    The liberal coverage condition fails in class MagicMerge
      for functional dependency: m1 -> m2
    Reason: lhs type UnsafeBase (UnsafeBase base err1) err2
      does not determine rhs type UnsafeBase dstBase err1
  In the instance declaration for
    MagicMerge (UnsafeBase (UnsafeBase base err1) err2) (UnsafeBase dstBase err1)

Which is of course right, but is completely unhelpfull! When we run the same program against GHC-7.6, we get another message:

  No instance for (MagicMerge (UnsafeBase base err2) dstBase)
    arising from a use of `magicMerge'
  Possible fix:
    add an instance declaration for
    (MagicMerge (UnsafeBase base err2) dstBase)
  In the second argument of `($)', namely
    `magicMerge (Error e :: UnsafeBase base err2 a)'
  In the expression:
    Other $ magicMerge (Error e :: UnsafeBase base err2 a)
  In a case alternative:
      Error e -> Other $ magicMerge (Error e :: UnsafeBase base err2 a)

And it contains a very helpfull information about inferred types. The information is very usefull, especialy when developing more complex instances.

It is VERY IMPORTANT to notice, that when we use the inferred context, the code compiles in both, GHC-7.8 and GHC-7.6! Right now I have to use both versions of GHC side by side, to be able to develop my instances faster.

So If we add the context inferred by GHC-7.6:

{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UndecidableInstances #-}

data UnsafeBase base err val = Value val
                             | Error err
                             | Other (base val)
                             deriving (Show, Eq)

class MagicMerge m1 m2 | m1 -> m2 where
    magicMerge :: m1 a -> m2 a


instance MagicMerge (UnsafeBase (UnsafeBase base err) err) (UnsafeBase base err) where
    magicMerge ma = case ma of
        Value a -> Value a
        Error e -> Error e
        Other o -> o

instance (MagicMerge (UnsafeBase base err2) dstBase) => MagicMerge (UnsafeBase (UnsafeBase base err1) err2) (UnsafeBase dstBase err1) where
    magicMerge (ma :: UnsafeBase (UnsafeBase base err1) err2 a) = case ma of
        Value a -> Value a
        Error e -> Other $ magicMerge (Error e :: UnsafeBase base err2 a)
        Other o -> case o of
            Value a  -> Other $ magicMerge (Value a  :: UnsafeBase base err2 a)
            Error e  -> Error e
            Other o' -> Other $ magicMerge (Other o' :: UnsafeBase base err2 a)


main = print "help me world!"

The code compiles and works ok in both GHC-7.6 and GHC-7.8. In such cases, GHC-7.8 should inform about lacking premises.

Change History (6)

comment:1 Changed 12 months ago by danilo2

  • Description modified (diff)

comment:2 Changed 12 months ago by danilo2

  • Priority changed from normal to high

comment:3 Changed 12 months ago by thoughtpolice

  • Milestone set to 7.10.1

Moving to 7.10.1.

comment:4 Changed 12 months ago by simonpj

Interesting example. See all the discussion on #8634.

The interesting thing here is that (using the vocabulary of #8634)

  • The initial error message might suggest -XDysFunctionalDepenencies
  • Adding -XDysFunctionalDependencies would yield the error in GHC 7.6
  • Adding the suggested context to the instance declaration would remove the need for -XDysFunctionalDependencies again!

If we implement the DYSFUNCTIONAL thing on a per-instance basis, as #8634 suggests, we should also warn when it is used but is not necessary.

Simon

comment:5 Changed 12 months ago by danilo2

@simonpj: This is exactly what I'm doing right now. If I migh suggest one thing - maybe it would be better to just report to the user 2 separate errors at once? One about not met liberal coverage condition and the second analogous to the one known from ghc-7.6?
This just saves a lot of time with adding and removing flags :)

comment:6 Changed 5 months ago by thoughtpolice

  • Milestone changed from 7.10.1 to 7.12.1

Moving to 7.12, as this doesn't look like it will be fixed in the 7.10 timeframe.

Note: See TracTickets for help on using tickets.