ekmett/reflection

Typeable Reflection

Closed this issue · 9 comments

It would be extremely useful to be able to get a typeRep for reflected types. Specifically, I'm hoping that (Reifies s a, Typeable a) => Typeable s, where show $ typeRep (Proxy :: Proxy s) outputs a unique ID, perhaps using TemplateHaskell support for global names, or something else like Data.Unique.ID.

I don't know much about the magic going on in reify, but is something like this doable?

i'm not sure this is possible with the current main operation, reify

Consider the type

reify :: forall a r. a -> (forall s. Reifies s a => Proxy s -> r) -> r

in this context, s is made unique via a existential, and is some sense both unique and local.

could you explain your use case?

As you might expect, it's for dynamic typing. Specifically, I'm trying to store a type in an environment with the syntactic library. Unfortunately, I don't know much about how this would work as the Typeable code hasn't been implemented yet.

I do know it would require a Typeable instance for storing our data type newtype Zq q = Zq Int, which represents modular arithmetic. We're using a reified modulus, so a Typeable instance for Zq q would require Typeable q. You can see a bit more detail at my question here, though that refers to GHC 7.6, and I'm using 7.8 now.

try out just using autoderivetypeable in 7.8

per se everything is typeable in ghc 7.8... and it might change to being "autotypedable by default" for 7.10

I'm not sure what you mean.

{-# LANGUAGE AutoDeriveTypeable #-}

import Data.Reflection
import Data.Typeable

main :: IO ()
main = reify (3 :: Int) (\ p -> print $ show $ typeRep p)

does not compile in GHC 7.8, it says:

Could not deduce (Typeable s) arising from a use of ‘typeRep’
from the context (Reifies s Int)

Similarly, defining the data type Zq, I can print typeRep (Proxy :: Proxy Zq), but not typeRep (Proxy :: Proxy (Zq q)) for a reified q.

lens currently includes a form of Typeable Reflection.

reifyTypeable :: Typeable a => a -> (forall s. (Typeable s, Reifies s a) => Proxy s -> r) -> r

http://hackage.haskell.org/package/lens-4.1.2/docs/Control-Lens-Internal-Reflection.html

I could in theory backport it here to the main reflection project.

Unfortunately, it is based on something close to the original approach to reflection by Oleg Kiselyov and Chung-chieh Shan. That means it is a couple of orders of magnitude slower than normal reflection.

A form of typeable reflection is implemented inside of lens these days. It was needed to make Control.Exception.Lens work after changes were made to Typeable.

http://hackage.haskell.org/package/lens-4.11.1/docs/Control-Lens-Internal-Reflection.html

We could think about moving it back home to here.

It's been moved, so this issue can, technically, be closed. However, the code has no comments in it and is far from obvious. The Typeable a constraint seems very strange from the outside; everything else seems strange from the inside.

The implementation does what it needs to do to let me fabricate Exception instances in a post-AutoDeriveTypeable world. I could definitely stand to document it better, but it is basically the old slow path with a slight tweak.