Changes to Typeable

Simon Peyton-Jones simonpj at microsoft.com
Wed Oct 3 14:01:15 CEST 2012


Aha.  Gabor, you're right.  Here's my summary. 

* As soon as we allow constraint kinds, we can abstract over them.  Example:
   data T (c :: * -> Constraint) = MkT (forall a. c a => a -> a)

* Hence, (T Eq) and (T Num) are valid types.

* Hence they need to be Typable

* And hence we must have something very like
     instance Typeable Eq where ...

* All this is fine.  But we don't (ever) want the programmer to write
   any instance of Typeable; that ways lies seg-faults, since we may
   rely on their veracity.

* For normal type we can say "use deriving", but not for classes,
   which don't have a deriving clause

* We could use "standalone deriving"
     deriving instance Typeable Eq

* Or alternatively we could make every data type and class
   an instance of Typeable automatically; that would save tons
   of lookup in the massive Typeable-instance table.

   On reflection I'm quite in favour of this.

* If we do make Typeable instances by default, there are two paths
   Plan A (easy): make GHC derive Typeable for everything, deprecate
            all uses of 'deriving Typeable'.  Small downside: some programs
            that are currently rejected will be accepted.

   Plan B (tiresome): have AutoDeriveTypable as an extension.  That
           means maintaining the massive instance table.

   Personally I vote for Plan A.   It's easier and more efficient to implement,
   and the upside of Plan B is modest in the extreme.

Opinions from anyone else?

Simon

|  -----Original Message-----
|  From: Gábor Lehel [mailto:illissius at gmail.com]
|  Sent: 25 September 2012 10:30
|  To: Simon Peyton-Jones
|  Cc: libraries at haskell.org
|  Subject: Re: Changes to Typeable
|  
|  On Mon, Sep 24, 2012 at 6:28 PM, Simon Peyton-Jones
|  <simonpj at microsoft.com> wrote:
|  > |  - Will it be possible to write e.g. deriving instance Typeable Eq?
|  >
|  > Not at the moment; we've only been thinking about Typable for things whose
|  kinds bottom out in *, not Constraint.  There doesn't seem to be any fundamental
|  obstacle -- but I can't yet see how it would be useful.
|  
|  One aspect is that if you have SomeType :: Constraint -> * and want
|  Typeable for SomeType c, which is *, you need Typeable c.
|  
|  But the particular application I had in mind is that you could
|  implement OO-style casting-to-interfaces in a relatively clean way.
|  
|  class InterfaceCastable a where
|      icast :: Typeable c => Proxy c -> a -> Maybe (Interface c)
|  
|  data Interface c = forall a. (c a, InterfaceCastable a) => Interface a
|  
|  instance InterfaceCastable (Interface c) where icast (Interface a) = icast a
|  
|  deriveInterfaceCastable :: Name -> Q [Dec]
|  
|  deriveInterfaceCastable could, for example, generate a Map TypeRep (a
|  -> Any) based on the instances in scope for the named type, where the
|  (a -> Any) is in reality a -> Interface c and the TypeRep is typeOf c,
|  and then icast looks up the TypeRep for the constraint that it got,
|  applies the function to its 'a' argument, and then unsafeCoerces the
|  result back to Interface c. Which might be going into too much detail,
|  but the point is that Typeable on constraints would be useful.
|  (Workarounds are possible, the reason I ask whether this will be
|  possible is whether it's worth working on them.)
|  
|  >
|  > |  - How about deriving instance Typeable Typeable? (It seems Proxy Proxy
|  > |  works, so maybe this would too.)
|  >
|  > Ditto.
|  >
|  > |  - Does it make sense to have an instance for (~)?
|  >
|  > Ditto.
|  >
|  > |  - Will instances be provided for the types in base and built-in to GHC?
|  >
|  > Yes, that would make sense.
|  
|  I should have said "for types which don't already have them and now
|  could". But it seems you got my meaning.
|  
|  >
|  > |  Automatically generate Typeable instances for every type constructor
|  > |  that is declared. 'deriving Typeable' becomes a no-op.
|  >
|  > Well, at the moment a type ONLY becomes an instance of a class if you ask for it
|  to be so, so your proposal would be a change of principle.  Sometimes *omitting*
|  an instance declaration may be important (eg to prevent a type being
|  serialisable).   That said, I can't see when I'd want a type not to be Typeable.  I
|  suppose it could be a compiler option.  I think the questions here are ones of
|  software engineering rather than being technical.
|  
|  Yes, it would be unorthodox. And it's definitely not applicable
|  willy-nilly to other classes (where not having an instance can be
|  important, as you say). But at the moment the only consequence I see
|  of having to derive Typeable manually is hassle, with no upside.
|  Typeable is increasingly a language feature rather than a library,
|  with manual instances getting more-and-more discouraged, this would
|  just take that train of thought further.
|  
|  Although, even if this were implemented, you would still need
|  'deriving Typeable' if you wanted to stay backwards compatible; and
|  because it's a significant change to the language you would presumably
|  have to hide it behind a language pragma, at which point instead of
|  {-# LANGUAGE AutoDeriveTypeable #-} you might as well write 'deriving
|  Typeable'; so maybe it wouldn't be so useful in practice.
|  
|  >
|  > Simon
|  >
|  
|  
|  
|  --
|  Your ship was destroyed in a monadic eruption.





More information about the Libraries mailing list