Opened 7 years ago

Closed 7 years ago

Last modified 2 years ago

#7742 closed bug (invalid)

StandaloneDeriving on Read fails for GADTs

Reported by: hoffstaetter Owned by:
Priority: normal Milestone:
Component: Compiler Version: 7.6.2
Keywords: deriving Cc:
Operating System: MacOS X Architecture: Unknown/Multiple
Type of failure: GHC rejects valid program Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description

Consider the following code that derives a Read instance for a GADT datatype:

data Foo a where
    Foo :: Show a => a -> Foo a
deriving instance Show (Foo a)

The above code works correctly. However, changing the "Show" constraint to "Read" will cause GHC to fail:

data Foo a where
    Foo :: Read a => a -> Foo a
deriving instance Read (Foo a)

with the error message:

    No instance for (Read a)
      arising from a use of `GHC.Read.readPrec'
    In the first argument of `Text.ParserCombinators.ReadPrec.step', namely
      `GHC.Read.readPrec'
    In a stmt of a 'do' block:
      a1 <- Text.ParserCombinators.ReadPrec.step GHC.Read.readPrec
    In the second argument of `Text.ParserCombinators.ReadPrec.prec', namely
      `do { Text.Read.Lex.Ident "Foo" <- GHC.Read.lexP;
            a1 <- Text.ParserCombinators.ReadPrec.step GHC.Read.readPrec;
            return (Foo a1) }'
    When typechecking the code for  `GHC.Read.readPrec'
      in a standalone derived instance for `Read (Foo a)':
      To see the code I am typechecking, use -ddump-deriv

A workaround is to place an additional Read constraint on the deriving clause:

data Foo a where
    Foo :: Read a => a -> Foo a
deriving instance Read a => Read (Foo a)

Change History (3)

comment:1 Changed 7 years ago by kosmikus

I think GHC is correct here.

Ignoring readsPrec for simplicity and just looking at read, you are trying to derive a function of String -> Foo a here. But in order to produce a Foo a, we have to construct a Read a dictionary. And there's no way to come up with one for an arbitrary a. That's why you need an external Read a constraint.

The situation is quite different for Show, because then you're provided with a Foo a, can extract the Show dictionary hidden within and use that to produce a textual representation of the a.

comment:2 Changed 7 years ago by monoidal

Resolution: invalid
Status: newclosed

I agree with kosmikus. instance Show (Foo a) can be written manually, while instance Read (Foo a) cannot.

comment:3 Changed 2 years ago by RyanGlScott

Keywords: deriving added
Note: See TracTickets for help on using tickets.