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