th-desugar: Functions to desugar Template Haskell

[ bsd3, library, template-haskell ] [ Propose Tags ]

This package provides the Language.Haskell.TH.Desugar module, which desugars Template Haskell's rich encoding of Haskell syntax into a simpler encoding. This desugaring discards surface syntax information (such as the use of infix operators) but retains the original meaning of the TH code. The intended use of this package is as a preprocessor for more advanced code manipulation tools. Note that the input to any of the ds... functions should be produced from a TH quote, using the syntax [| ... |]. If the input to these functions is a hand-coded TH syntax tree, the results may be unpredictable. In particular, it is likely that promoted datatypes will not work as expected.


[Skip to Readme]

Downloads

Note: This package has metadata revisions in the cabal description newer than included in the tarball. To unpack the package including the revisions, use 'cabal get'.

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 1.0.0, 1.1.0, 1.1.1, 1.2.0, 1.2.1, 1.3.0, 1.3.1, 1.4.0, 1.4.1, 1.4.2, 1.4.2.1, 1.5, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.4.1, 1.5.5, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.13.1, 1.14, 1.15, 1.16
Change log CHANGES.md
Dependencies base (>=4.7 && <5), containers (>=0.5), fail (>=4.9 && <4.10), ghc-prim, mtl (>=2.1 && <2.3), ordered-containers (>=0.2.2), semigroups (>=0.16), syb (>=0.4), template-haskell (>=2.9 && <2.19), th-abstraction (>=0.4 && <0.5), th-lift (>=0.6.1), th-orphans (>=0.13.7), transformers-compat (>=0.6.3) [details]
License BSD-3-Clause
Author Richard Eisenberg <rae@cs.brynmawr.edu>
Maintainer Ryan Scott <ryan.gl.scott@gmail.com>
Revised Revision 1 made by ryanglscott at 2022-05-20T00:52:57Z
Category Template Haskell
Home page https://github.com/goldfirere/th-desugar
Bug tracker https://github.com/goldfirere/th-desugar/issues
Source repo this: git clone https://github.com/goldfirere/th-desugar.git(tag v1.10)
head: git clone https://github.com/goldfirere/th-desugar.git -b master
Uploaded by ryanglscott at 2021-10-31T01:05:33Z
Distributions Arch:1.14, Debian:1.10, LTSHaskell:1.15, NixOS:1.15, Stackage:1.16
Reverse Dependencies 17 direct, 310 indirect [details]
Downloads 45267 total (203 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2021-10-31 [all 1 reports]

Readme for th-desugar-1.13

[back to package description]

th-desugar Package

Hackage Build Status

This package provides the Language.Haskell.TH.Desugar module, which desugars Template Haskell's rich encoding of Haskell syntax into a simpler encoding. This desugaring discards surface syntax information (such as the use of infix operators) but retains the original meaning of the TH code. The intended use of this package is as a preprocessor for more advanced code manipulation tools. Note that the input to any of the ds... functions should be produced from a TH quote, using the syntax [| ... |]. If the input to these functions is a hand-coded TH syntax tree, the results may be unpredictable. In particular, it is likely that promoted datatypes will not work as expected.

One explicit goal of this package is to reduce the burden of supporting multiple GHC / TH versions. Thus, the desugared language is the same across all GHC versions, and any inconsistencies are handled internally.

The package was designed for use with the singletons package, so some design decisions are based on that use case, when more than one design choice was possible.

I will try to keep this package up-to-date with respect to changes in GHC.

Known limitations

Limited support for kind inference

th-desugar sometimes has to construct types for certain Haskell entities. For instance, th-desugar desugars all Haskell98-style constructors to use GADT syntax, so the following:

data T (a :: k) = MkT (Proxy a)

Will be desugared to something like this:

data T (a :: k) where
  MkT :: forall k (a :: k). Proxy a -> T (a :: k)

Notice that k is explicitly quantified in the type of MkT. This is due to an additional pass that th-desugar performs over the type variable binders of T to extract all implicitly quantified variables and make them explicit. This makes the desugared types forwards-compatible with a future version of GHC that requires all kind variables in a top-level forall to be explicitly quantified.

This process of extracting all implicitly quantified kind variables is not perfect, however. There are some obscure programs that will cause th-desugar to produce type variable binders that are ill scoped. Here is one example:

data P k (a :: k)
data Foo (a :: Proxy j) (b :: k) c = MkFoo c (P k j)

If you squint hard at MkFoo, you'll notice that j :: k. However, this relationship is not expressed syntactically, which means that th-desugar will not be aware of it. Therefore, th-desugar will desugar Foo to:

data Foo (a :: Proxy j) (b :: k) c where
  MkFoo :: forall j k (a :: Proxy j) (b :: k) c.
           c -> P k j -> Foo (a :: Proxy j) (b :: k) c

This is incorrect since k must come before j in order to be well scoped. There is a workaround to this issue, however: add more explicit kind information. If you had instead written this:

data Foo (a :: Proxy (j :: k)) (b :: k) c = MkFoo c (P k j)

Then the fact that j :: k is expressed directly in the AST, so th-desugar is able to pick up on it and pick forall k j (a :: Proxy j) (b :: k) c. <...> as the telescope for the type of MkFoo.

The following constructs are known to be susceptible to this issue:

  1. Desugared Haskell98-style constructors
  2. Locally reified class methods
  3. Locally reified record selectors
  4. Locally reified data constructors
  5. Locally reified type family instances (on GHC 8.8 and later, in which the Template Haskell AST supports explicit foralls in type family equations)

Limited support for linear types

Currently, the th-desugar AST deliberately makes it impossible to represent linear types, and desugaring a linear function arrow will simply turn into a normal function arrow (->). This choice is partly motivated by issues in the way that linear types interact with Template Haskell, which sometimes make it impossible to tell whether a reified function type is linear or not. See, for instance, GHC#18378.