Skip to content

Type name confusion #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ryanreich opened this issue Oct 26, 2017 · 5 comments
Closed

Type name confusion #42

ryanreich opened this issue Oct 26, 2017 · 5 comments

Comments

@ryanreich
Copy link

ryanreich commented Oct 26, 2017

The interpreter's type checker produces a clearly wrong error when the interpreted expression evaluates to a type synonym whose definition contains a qualified-imported type constructor whose native name is the same as the synonym. See simple.zip for a minimal example (stack project).

Looking at the source, it seems to me that the problem is in the code

interpret :: (MonadInterpreter m, Typeable a) => String -> a -> m a
interpret expr wit = unsafeInterpret expr (show $ Data.Typeable.typeOf wit)

because Typeable's string representation doesn't give the fully qualified name of the type constructors.

Renaming the type synonym actually doesn't help, for the same reason: the compiler then complains that it can't find the imported type constructor. You have to simply avoid using a type synonym altogether, since Typeable (of course) doesn't print the name of the synonym but its expansion.

@mvdan
Copy link
Contributor

mvdan commented Oct 27, 2017

This goes beyond my Haskell-fu, I'm afraid. If you believe you have a fix for this issue, feel free to add a test for this case and do the appropriate change, making sure all the tests pass.

/cc @Simspace

@gelisam
Copy link
Contributor

gelisam commented Oct 27, 2017

I assume you meant to cc me, not my employer :)

I am familiar with that bug, I had to work around it in hawk. The fix would be to always quantify the type with its module name. That doesn't look too hard:

typeOf :: Typeable a => a -> TypeRep a
typeRepTyCon :: TypeRep a -> TyCon
tyConModule :: TyCon -> String

@mvdan
Copy link
Contributor

mvdan commented Oct 27, 2017

I'm so sorry - misread the github UI.

@gelisam
Copy link
Contributor

gelisam commented Feb 17, 2020

Hmm! This is more difficult than I though. Qualifying the type with its module name was easy, but that only helps if the type synonym resolves to a type from a module which is imported under its fully-qualified name.

@ryanreich's simple.zip 404s for me, but a simple reproducer is interpret "Data.Typeable.typeOf ()" (as :: Data.Typeable.TypeRep). In Data.Typeable, TypeRep is a type synonym for Data.Typeable.Internal.SomeTypeRep. That's bad news, because Data.Typeable.Internal is an internal module which we cannot import. So in this case, qualifying the type would make the situation worse: without the qualifier, we can still figure out that we can import Type.Reflection unqualified in order to bring SomeTypeRep into scope. With the qualifier... I guess we can still do it, using import Type.Reflection as Data.Typeable.Internal, but that's a pretty terrible hack.

So, if Foo is a type synonym for Bar.Foo but Bar is not imported (or worse, non-importable), then generating "expr :: Bar.Foo" instead of "expr :: Foo" doesn't help. Even if Bar is imported, some extra care is needed because it might be imported via import qualified Bar as B, in which case it's "expr :: B.Foo" which we have to generate.

Since it is generating the name of the type which is tricky, I thought I could work around the problem by generating "toDyn expr :: Dynamic", and then using fromDynamic to cast that to Foo outside of the interpreter. That works for my interpret "typeOf ()" (as :: TypeRep) reproducer, because TypeRep has a Typeable instance. Unfortunately, this breaks polymorphic expressions like interpret "id" (as :: Int -> Int) because while Int -> Int has a Typeable instance, a -> a does not. Generating "id :: Int -> Int" is what caused the interpreter to specialize a -> a to Int -> Int; if I generate toDyn id :: Dynamic, the specialization doesn't happen. In order to get that specialization to happen, I really need to generate the name of the type.

I really don't know how, though. One possible clue: I noticed that on hackage, when looking at the documentation for Data.Typeable, clicking on SomeTypeRep navigates to the documentation for Type.Reflection, not the documentation for Data.Typeable.Internal. How does haddock know, and can we do the same thing?

@gelisam
Copy link
Contributor

gelisam commented Apr 18, 2020

#88 is a duplicate of this, but more work has happened in that ticket than this one, so let's close this one in favor of #88.

@gelisam gelisam closed this as completed Apr 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants