[GHC] #12159: Record-like GADTs with repeated fields (of same type) rejected

GHC ghc-devs at haskell.org
Wed Jun 8 22:19:50 UTC 2016


#12159: Record-like GADTs with repeated fields (of same type) rejected
-------------------------------------+-------------------------------------
        Reporter:  heisenbug         |                Owner:
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.0.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  GHC rejects       |  Unknown/Multiple
  valid program                      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 Gragghlel.  Look at `TcTyDecls`:
 {{{
 Note [GADT record selectors]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 For GADTs, we require that all constructors with a common field 'f' have
 the same
 result type (modulo alpha conversion).  [Checked in
 TcTyClsDecls.checkValidTyCon]
 E.g.
         data T where
           T1 { f :: Maybe a } :: T [a]
           T2 { f :: Maybe a, y :: b  } :: T [a]
           T3 :: T Int

 and now the selector takes that result type as its argument:
    f :: forall a. T [a] -> Maybe a

 Details: the "real" types of T1,T2 are:
    T1 :: forall r a.   (r~[a]) => Maybe a -> T r
    T2 :: forall r a b. (r~[a]) => Maybe a -> b -> T r

 So the selector looks like this:
    f :: forall a. T [a] -> Maybe a
    f (a:*) (t:T [a])
      = case t of
          T1 c   (g:[a]~[c]) (v:Maybe c)       -> v `cast` Maybe (right
 (sym g))
          T2 c d (g:[a]~[c]) (v:Maybe c) (w:d) -> v `cast` Maybe (right
 (sym g))
          T3 -> error "T3 does not have field f"
 }}}
 An alternative design choice would be this:

  * A field is "naughty" if its type, in any constructor, mentions any
 existential type variables
  * Generate selectors only for non-naughty fields
  * Allow updates only of non-naughty fields

 In the example above, `f` is naughty because `T1`'s real type is
 {{{
    T1 :: forall r a.   (r~[a]) => a -> T r
 }}}
 And `f :: Maybe a` mentions the existential variable `a`.  In contrast, in
 the example from the description
 {{{
 data Foo p where
   Bar :: { quux :: Bool } -> Foo Char
   Baz :: { quux :: Bool } -> Foo Int
 }}}
 `quux :: Bool` mentions no existentials, so we can generate a perfectly
 fine selector.

 Under this scheme some fields that currently get record selectors would
 not get them, and vice versa.

 ------
 I think this would be a good change

 * It'd mean that we used the same rule for record selectors as for record
 updates.  Currently they are different; compare
   * `Note [Naughty record selectors]` in `TcTyDecls`
   * `Note [Criteria for update]` in `TcExpr`

 * We have at least two Trac tickets wanting behaviour (this one and
 #8673).

 * I dont' know anyone who needs the existing behaviour.  (E.g. in data
 type `T` above, `f` would no longer get a record selector, although you
 could write one by hand.)

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12159#comment:4>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list