<div dir="ltr">In practice I find that almost every piece of template-haskell code I've written gets broken by something every other release of GHC, so it hasn't exactly been a shining beacon of backwards compatibility thus far.<div><br></div><div>Invariably it is always missing _something_ that I need, and anything that ties it to a more canonical form like this would be a very good thing. <br><div><br></div><div>I'd strongly support this move.</div><div><br></div><div>A sample just from my current working directory:</div><div>
<p class=""><span class=""><font face="monospace, monospace" size="1">haskell> grep -r MIN_VERSION_template_haskell */src</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH/Internal.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH/Internal.hs:#if MIN_VERSION_template_haskell(2,7,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH/Internal.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH/Internal.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH/Internal.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH/Internal.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH.hs:#ifndef MIN_VERSION_template_haskell</font></span></p>
<p class=""><span style="font-family:monospace,monospace;font-size:x-small">bifunctors/src/Data/Bifunctor/TH.hs:#if __GLASGOW_HASKELL__ < 710 && MIN_VERSION_template_haskell(2,8,0)</span><br></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH.hs:#if MIN_VERSION_template_haskell(2,7,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH.hs:#if MIN_VERSION_template_haskell(2,7,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH.hs:#if MIN_VERSION_template_haskell(2,7,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH.hs:#if MIN_VERSION_template_haskell(2,7,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH.hs:#if MIN_VERSION_template_haskell(2,7,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH.hs:# if __GLASGOW_HASKELL__ >= 710 || !(MIN_VERSION_template_haskell(2,8,0))</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">bifunctors/src/Data/Bifunctor/TH.hs:#if MIN_VERSION_template_haskell(2,7,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">free/src/Control/Monad/Free/TH.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Control/Lens/Internal/FieldTH.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Control/Lens/Internal/TH.hs:#ifndef MIN_VERSION_template_haskell</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Control/Lens/Internal/TH.hs:#define MIN_VERSION_template_haskell(x,y,z) (defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 706)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Control/Lens/Internal/TH.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span style="font-family:monospace,monospace;font-size:x-small">lens/src/Control/Lens/Plated.hs:#if !(MIN_VERSION_template_haskell(2,8,0))</span><br></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Control/Lens/TH.hs:#ifndef MIN_VERSION_template_haskell</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Control/Lens/TH.hs:#define MIN_VERSION_template_haskell(x,y,z) (defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 706)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Control/Lens/TH.hs:#if !(MIN_VERSION_template_haskell(2,7,0))</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Control/Lens/TH.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Control/Lens/TH.hs:#if !(MIN_VERSION_template_haskell(2,7,0))</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#ifndef MIN_VERSION_template_haskell</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#define MIN_VERSION_template_haskell(x,y,z) 1</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if !MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if !MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if !MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if !MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">lens/src/Language/Haskell/TH/Lens.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">linear/src/Linear/V.hs:#ifdef MIN_VERSION_template_haskell</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">linear/src/Linear/V.hs:#if !(MIN_VERSION_reflection(1,3,0)) && defined(MIN_VERSION_template_haskell)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">linear/src/Linear/V.hs:#if !(MIN_VERSION_reflection(1,3,0)) && defined(MIN_VERSION_template_haskell)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">nats/src/Numeric/Natural.hs:#if defined(MIN_VERSION_hashable) || defined(MIN_VERSION_template_haskell)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">nats/src/Numeric/Natural.hs:#ifdef MIN_VERSION_template_haskell</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">nats/src/Numeric/Natural.hs:#ifdef MIN_VERSION_template_haskell</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">tables/src/Data/Table.hs:#if MIN_VERSION_template_haskell(2,10,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">tables/src/Data/Table.hs:#if MIN_VERSION_template_haskell(2,9,0)</font></span></p>
<p class=""><span style="font-family:monospace,monospace;font-size:x-small">tagged/src/Data/Proxy/TH.hs:#if MIN_VERSION_template_haskell(2,8,0)</span><br></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">tagged/src/Data/Proxy/TH.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">tagged/src/Data/Proxy/TH.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p>
<p class=""><span class=""><font face="monospace, monospace" size="1">tagged/src/Data/Proxy/TH.hs:#if MIN_VERSION_template_haskell(2,8,0)</font></span></p></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 11, 2015 at 12:46 PM, Eric Seidel <span dir="ltr"><<a href="mailto:eric@seidel.io" target="_blank">eric@seidel.io</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I think backwards-compatibility is still a potential issue, not because<br>
the pattern/type synonym layer seems implausible, but because I suspect<br>
people will begin to sidestep the compatibility layer and just use the<br>
GHC API (I certainly would). GHC is not shy about breaking<br>
backwards-compatibility between major releases, so it seems possible<br>
that this could extend to breaking TH. Missing features is not nearly as<br>
bad as breaking most clients of TH.<br>
<br>
But perhaps this isn't a very likely scenario. TH mostly exports<br>
datatypes for haskell syntax, smart constructors, and a few functions<br>
for looking up metadata. I doubt these pieces of GHC change very often,<br>
and when they do it's probably an extension rather than a breaking<br>
change. Someone with more historical knowledge of GHC could comment :)<br>
<br>
All in all, I like this idea a lot!<br>
<span class="HOEnZb"><font color="#888888"><br>
Eric<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
On Wed, Nov 11, 2015, at 08:26, Richard Eisenberg wrote:<br>
> Hi devs,<br>
><br>
> There's a bunch of open tickets around Template Haskell. A great many of<br>
> them are attempts to make TH more like what's already in GHC. Of course,<br>
> when someone improves GHC, then TH also has to be updated. But this<br>
> doesn't always happen, leading to several of these tickets.<br>
><br>
> I believe I have a solution to the problem: just eliminate Template<br>
> Haskell and provide direct access to GHC's internal structures. The idea<br>
> (still very sketchy; hence pre-proposal) is like this (numbered for easy<br>
> reference, but no order is implied):<br>
><br>
> 1. TH quotes would remain. DsMeta would desugar quotes into Core code<br>
> that produces HsExprs. For example, [| 1 |] would have type (Q (LHsExpr<br>
> Name)). (Or perhaps (Q (LHsExpr RdrName)) if that works out better for<br>
> clients.)<br>
><br>
> 2. TH splices would remain, working much as they do now. The expression<br>
> inside, say, an expression splice would have type (Q exp) where we can<br>
> satisfy the constraint (SpliceExpr exp). There would be instances for<br>
> (SpliceExpr (LHsExpr Name)) and (SpliceExpr (LHsExpr RdrName)) as well as<br>
> the non-located variants. Generalizing the type of expressions here<br>
> allows users not to worry about un-renaming when roundtripping between<br>
> quotes and splices.<br>
><br>
> 3. Reification would remain, using an Info structure much like we have<br>
> now. Would we expose the real GHC TyCons as the result of reification? Or<br>
> is it better to give the users HsDecls? This would need to be fleshed<br>
> out.<br>
><br>
> 4. Lifting would remain, doing the obvious thing.<br>
><br>
> 5. The template-haskell package could even remain, as a<br>
> backward-compatibility shim. It would declare gobs of pattern synonyms<br>
> and type synonyms to wrap the new underlying interface. This re-imagined<br>
> template-haskell package would not need to be a boot library, and could<br>
> be upgraded separately from GHC. We could even maintain multiple versions<br>
> of the library so that TH clients wouldn't have to change their code when<br>
> GHC upgrades. Perhaps someday we could think about deprecating, if that's<br>
> the way the wind blows.<br>
><br>
> So, the end result is a completely re-engineered TH, but I believe we<br>
> could keep full backward compatibility. (I have not considered Typed TH<br>
> in any depth yet. But my hope is that it's not too different from the<br>
> above.) And, we're left with a significantly lower maintenance burden,<br>
> especially if we eliminate template-haskell someday.<br>
><br>
> And, tantalizingly, the flexibility in splices might allow us to splice<br>
> in *Core* code someday. Perhaps we could also reify Core code. Then<br>
> clients could write their own custom, domain-aware optimizations. Like<br>
> RULES on steroids. But that's all for the next phase. (Giving due credit,<br>
> this last bit is inspired by work David Christiansen is doing in Idris.)<br>
><br>
> What's wrong with this idea? I feel like *something* has to be more<br>
> complicated than I've made it seem!<br>
><br>
> Richard<br>
> _______________________________________________<br>
> ghc-devs mailing list<br>
> <a href="mailto:ghc-devs@haskell.org">ghc-devs@haskell.org</a><br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><br>
_______________________________________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org">ghc-devs@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><br>
</div></div></blockquote></div><br></div>