[GHC] #13140: Handle subtyping relation for roles in Backpack

GHC ghc-devs at haskell.org
Thu Feb 23 10:26:36 UTC 2017


#13140: Handle subtyping relation for roles in Backpack
-------------------------------------+-------------------------------------
        Reporter:  ezyang            |                Owner:  ezyang
            Type:  feature request   |               Status:  patch
        Priority:  normal            |            Milestone:  8.4.1
       Component:  Compiler (Type    |              Version:  8.1
  checker)                           |             Keywords:  backpack hs-
      Resolution:                    |  boot
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):  Phab:D3123
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by ezyang):

 On SPJ's request: here are concrete examples showing that no choice of
 existing role is suitable for being "abstract":

 * Suppose we pick `nominal` to be abstract. Let `T` be `nominal` in its
 first argument: if we have `T a ~R T b`, we can derive `a ~N b`. Now set
 `T` to `phantom`, then we have `Int ~P Bool` and consequently `T Int ~R T
 Bool`. This lets us derive `Int ~N Bool`, bad!

 * Suppose we pick `phantom` to be abstract. Let `T` be `phantom` in its
 first argument: then we have `T Int ~R T Bool` for all a and b. Now set
 `T` to `nominal`; if `T a ~R T b`, then `a ~N b`; thus we have `Int ~N
 Bool`. Bad!

 * Suppose we pick `representational` to be abstract. Let `T` be
 `representational` in its first argument: then we have that if `T a ~R T
 b`, then `a ~R b`. Now set `T` to `phantom`, then we have `Int ~P Bool`
 and consequently `T Int ~R T Bool`. But this implies `Int ~R Bool`, bad!
 (You can also do the other proof on this one.)

 Another question was this: why doesn't subroling break this way? Subroling
 says that if we have a type variable `a` at some role ρ, we can use it at
 role ρ' so long as ρ <= ρ'. (N is a subrole of everything).  So for
 example, the following is acceptable:

 {{{
 data T a = MkT a
 type role S nominal
 data S a = MkS (T a)
 }}}

 In S, a is at role nominal, but we can pass it to a T which has a at role
 representational. What we are afraid of is having `T a ~R T b` imply `a ~N
 b` by using S. But from the hypothesis we get is `a ~R b`, which does NOT
 imply `S a ~R S b` (S is nominal!).

 Another interesting observation is how we treat a polymorphic type
 constructor, e.g., m in `forall m. m a -> m a`. Via the Co_App rule, to
 show `m a ~ρ m' b` we must show `m ~N m'` and `a ~ρ b` (like the nominal
 role). Via the Co_Left rules, we can only say `a ~N b` if `m a ~N m' b`
 (just like the phantom role, we learn nothing when `m a ~R m' b`). So the
 "abstract" role implicitly falls out of the way the coercion formation
 rules handle type variables!

 All of this seems like evidence that adding an abstract role annotation is
 "the right thing to do."

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


More information about the ghc-tickets mailing list