[GHC] #11011: Type-indexed TypeReps, Static Pointers and Distributed Closures

GHC ghc-devs at haskell.org
Mon Oct 26 13:24:28 UTC 2015


#11011: Type-indexed TypeReps, Static Pointers and Distributed Closures
-------------------------------------+-------------------------------------
        Reporter:  bjmprice          |                Owner:
            Type:  feature request   |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by goldfire):

 From the wiki:

 > To ease the transition we will provide both
 >    * The old API via a (deprecated) new module `Data.Typeable710`.
 >    * The old API via the exiting module `Data.Typeable` but with new
 names for (deprecated) old types and functions.

 This doesn't appear to ease the transition to me. It means forcing users
 to make a choice: 1) be lazy and change your import, or 2) educate
 themselves about our new interface, which involves a non-trivial amount of
 whiz-bang new features. Many will choose (1), because many people are
 lazy, especially in the face of type theory. Then those people will have
 to change again.

 Furthermore, this violates the "3-year no-warning maintenance window"
 policy being formulated on the libraries@ list.

 And, with a little type-level hackery, I think we can have our cake and
 eat it to: use just 1 set of names for both APIs. To wit:

 {{{#!hs
 data TypeRep710 = forall a. TypeRep710 (TypeRep80 a)
 data TypeRep80 :: k -> *

 type family TypeRep :: k where
   TypeRep = TypeRep710
   TypeRep = TypeRep80

 class Typeable (a :: k) where
   typeRep# :: Proxy# a -> TypeRep80 a

 type family TypeRepKind res where
   TypeRepKind (proxy (a :: k) -> b) = k
   TypeRepKind (TypeRep80 (a :: k)) = k

 class TypeRepResult res where
   type TypeRepIndex res :: TypeRepKind res
   typeRep :: Typeable (TypeRepIndex res) => res

 instance (b ~ TypeRep710) => TypeRepResult (proxy a -> b) where
   type TypeRepIndex (proxy a -> b) = a
   typeRep (_ :: proxy a) = TypeRep710 (typeRep :: TypeRep80 a)
 instance TypeRepResult (TypeRep80 a) where
   type TypeRepIndex (TypeRep80 a) = a
   typeRep = undefined
 }}}

 This works on my branch. The following definitions also work:

 {{{#!hs
 foo :: TypeRep -> ()
 foo = undefined

 bar :: TypeRep Int -> ()
 bar = undefined
 }}}

 where the first gets `TypeRep710` and the second gets `TypeRep80`. We also
 conveniently have `typeRep :: Typeable a => proxy a -> TypeRep` (where
 that's the `TypeRep710`) and `typeRep :: Typeable a => TypeRep a` (where
 that's the `TypeRep80`). In a few years, we just remove the compatibility
 shim. :)

 Do I honestly think this is a good idea? I'm not sure. But I don't have a
 better one that will keep everyone happy.

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


More information about the ghc-tickets mailing list