It's possible to define instances of Reifies directly, and in fact Data.Reflection does so for some types. This kind of scares me. The existing instances get in the way by overlapping, but if you remove them for a moment, you can consider something horrifying like this:
instance Reifies (s :: *) Int where
reflect _ = 12
Now if we have something like
f :: forall s proxy . Reifies s Int => proxy s -> Int
f p = reflect p
Well, GHC has an instance for that, so it can compile f directly to
f = /\ s proxy -> \ ( _ :: Reifies s Int) (_ :: proxy s) -> 12
If f is passed to reify, I don't think we get any guarantees.
Now as I mentioned, the current instances do get in the way of this horror by overlapping, which I believe prevents the premature specialization of f (s can't be shown to be apart from the various extant instances) but this whole thing makes me nervous, and I can't quite escape the nagging feeling that there could be some way to exploit it.
It's possible to define instances of
Reifiesdirectly, and in factData.Reflectiondoes so for some types. This kind of scares me. The existing instances get in the way by overlapping, but if you remove them for a moment, you can consider something horrifying like this:Now if we have something like
Well, GHC has an instance for that, so it can compile
fdirectly toIf
fis passed toreify, I don't think we get any guarantees.Now as I mentioned, the current instances do get in the way of this horror by overlapping, which I believe prevents the premature specialization of
f(scan't be shown to be apart from the various extant instances) but this whole thing makes me nervous, and I can't quite escape the nagging feeling that there could be some way to exploit it.