Adding an orphan instance locally helped (of course).
instanceLiftExpwherelift=pure
It appears to be the right thing to do... Why isn't this in Language.Haskell.TH.Syntax?
Just forgotten? If so, and somebody gives me a thumbs up, I'll add it tomorrow to HEAD (with a corresponding @since annotation).
Trac metadata
Trac field
Value
Version
8.2.1
Type
FeatureRequest
TypeOfFailure
OtherFailure
Priority
normal
Resolution
Unresolved
Component
Template Haskell
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
However, it should be noted that a derived Lift instance for Exp would not produce the code above. The problem with that instance is that if x :: Exp, then $(lift x) would not necessarily equal x (or even be of type Exp!), which is a rule you'd generally expect to hold. (I realize this law isn't started anywhere in the Haddocks at the moment, but it probably should be.)
However, it should be noted that a derived Lift instance for Exp would not produce the code above. The problem with that instance is that if x :: Exp, then $(lift x) would not necessarily equal x (or even be of type Exp!), which is a rule you'd generally expect to hold. (I realize this law isn't started anywhere in the Haddocks at the moment, but it probably should be.)
Interesting. I did not think about that too deeply. Maybe worth documenting this. But in my case (the specific usage in [e|eqTypeRep (typeRep @ Maybe)|]) the invariant is satisfied: lift eqTypeRep should encode an Exp. After all, I use it in this context [p|($here -> Just HRefl)|] as the view function. So I should be safe, right? Should I err, the type checker will remind me after quotation expansion, won't it?
What about the derivation mechanism for Lift instances? Will it do the right thing in this case too?
Let me try and articulate more precisely what this invariant is capturing. Here are some examples of the invariant at work:
{-# LANGUAGE TemplateHaskell #-}importLanguage.Haskell.TH.Syntaxtest::IO()test=mapM_print[$(liftTrue)==True,$(lift"hello")=="hello"]
These should all print True, and more generally, you should be able to stick in any other Bool or String and also have it print all Trues. But it's easy to subvert this with your proposed Lift Exp instance, since you can have, e.g.:
uhOh::ExpuhOh=lift"uhOh"
Now $(lift uhOh) won't be an Exp, but rather a String. This is not at all what we want.
Now calling lift on an Exp will produce an ExpQ that represents an Exp value. It's quite meta, granted, but that's how it should be :)
In any case, I've been meaning to resolve #14030 (closed) for a while now, but haven't had much time to look into it recently. One obstacle is that deriving Lift instances for data types in template-haskell during stage-1 compilation is harder than it sounds because GHC HEAD moved around the locations of functions that are used when deriving Lift instances themselves. Therefore, I think I'll have to disable generating Lift instances on stage-1 compilers for now to make it work, but I've yet to figure out how to accomplish that.
But it's easy to subvert this with your proposed Lift Exp instance, since you can have, e.g.:
uhOh::ExpuhOh=lift"uhOh"
You mean
uhOh::ExpQuhOh=lift"uhOh"
Now $(lift uhOh) won't be an Exp, but rather a String. This is not at all what we want.
Totally agree. My question is when this happens in a [p|($uhOh -> binding)|] and this ends up in a splice, ultimately being compiled by GHC, then I'll get a type error "Expected Exp, got: String", correct?
My question is when this happens in a [p|($uhOh -> binding)|] and this ends up in a splice, ultimately being compiled by GHC, then I'll get a type error "Expected Exp, got: String", correct?
Sure, GHC will definitely catch the mistake in the form of a (sometimes hard-to-scrutinize) type error. But I would still be frustrated that that happened in the first place, since it would violate my intuition of how lift interacts with splicing.