summaryrefslogtreecommitdiff
path: root/docs/users_guide/exts/template_haskell.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/users_guide/exts/template_haskell.rst')
-rw-r--r--docs/users_guide/exts/template_haskell.rst772
1 files changed, 772 insertions, 0 deletions
diff --git a/docs/users_guide/exts/template_haskell.rst b/docs/users_guide/exts/template_haskell.rst
new file mode 100644
index 0000000000..b7e0e4dff2
--- /dev/null
+++ b/docs/users_guide/exts/template_haskell.rst
@@ -0,0 +1,772 @@
+.. _template-haskell:
+
+Template Haskell
+================
+
+Template Haskell allows you to do compile-time meta-programming in
+Haskell. The background to the main technical innovations is discussed
+in "`Template Meta-programming for
+Haskell <http://research.microsoft.com/~simonpj/papers/meta-haskell/>`__"
+(Proc Haskell Workshop 2002).
+
+The `Template Haskell <http://www.haskell.org/haskellwiki/Template_Haskell>`__
+page on the GHC Wiki has a wealth of information. You may also consult the
+:th-ref:`Haddock reference documentation <Language.Haskell.TH.>`.
+Many changes to the original
+design are described in `Notes on Template Haskell version
+2 <https://www.haskell.org/ghc/docs/papers/th2.ps>`__.
+Not all of these changes are in GHC, however.
+
+The first example from that paper is set out below (:ref:`th-example`)
+as a worked example to help get you started.
+
+The documentation here describes the realisation of Template Haskell in
+GHC. It is not detailed enough to understand Template Haskell; see the
+`Wiki page <http://haskell.org/haskellwiki/Template_Haskell>`__.
+
+.. _th-syntax:
+
+Syntax
+------
+
+.. extension:: TemplateHaskell
+ :shortdesc: Enable Template Haskell.
+
+ :implies: :extension:`TemplateHaskellQuotes`
+ :since: 6.0. Typed splices introduced in GHC 7.8.1.
+
+ Enable Template Haskell's splice and quotation syntax.
+
+.. extension:: TemplateHaskellQuotes
+ :shortdesc: Enable quotation subset of
+ :ref:`Template Haskell <template-haskell>`.
+
+ :since: 8.0.1
+
+ Enable only Template Haskell's quotation syntax.
+
+Template Haskell has the following new syntactic constructions. You need to use
+the extension :extension:`TemplateHaskell` to switch these syntactic extensions on.
+Alternatively, the :extension:`TemplateHaskellQuotes` extension can be used to
+enable the quotation subset of Template Haskell (i.e. without splice syntax).
+The :extension:`TemplateHaskellQuotes` extension is considered safe under
+:ref:`safe-haskell` while :extension:`TemplateHaskell` is not.
+
+- A splice is written ``$x``, where ``x`` is an arbitrary expression.
+ There must be no space between the "$" and the expression.
+ This use of "$" overrides its meaning as an infix operator, just as "M.x"
+ overrides the meaning of "." as an infix operator. If you want the
+ infix operator, put spaces around it.
+
+ A top-level splice can occur in place of
+
+ - an expression; the spliced expression must have type ``Q Exp``
+
+ - a pattern; the spliced pattern must have type ``Q Pat``
+
+ - a type; the spliced expression must have type ``Q Type``
+
+ - a list of declarations at top level; the spliced expression must
+ have type ``Q [Dec]``
+
+ Inside a splice you can only call functions defined in imported
+ modules, not functions defined elsewhere in the same module. Note
+ that declaration splices are not allowed anywhere except at top level
+ (outside any other declarations).
+
+ The ``Q`` monad is a monad defined in ``Language.Haskell.TH.Syntax`` which
+ supports several useful operations during code generation such as reporting
+ errors or looking up identifiers in the environment.
+
+- A expression quotation is written in Oxford brackets, thus:
+
+ - ``[| ... |]``, or ``[e| ... |]``, where the "..." is an
+ expression; the quotation has type ``Quote m => m Exp``.
+
+ - ``[d| ... |]``, where the "..." is a list of top-level
+ declarations; the quotation has type ``Quote m => m [Dec]``.
+
+ - ``[t| ... |]``, where the "..." is a type; the quotation has type
+ ``Quote m => m Type``.
+
+ - ``[p| ... |]``, where the "..." is a pattern; the quotation has
+ type ``Quote m => m Pat``.
+
+ The ``Quote`` type class is the minimal interface necessary to implement
+ the desugaring of quotations. The ``Q`` monad is an instance of ``Quote`` but
+ contains many more operations which are not needed for defining quotations.
+
+ See :ref:`pts-where` for using partial type signatures in quotations.
+
+- Splices can be nested inside quotation brackets. For example the fragment
+ representing ``1 + 2`` can be constructed using nested splices::
+
+ oneC, twoC, plusC :: Quote m => m Exp
+ oneC = [| 1 |]
+
+ twoC = [| 2 |]
+
+ plusC = [| $oneC + $twoC |]
+
+- The precise type of a quotation depends on the types of the nested splices inside it::
+
+ -- Add a redundant constraint to demonstrate that constraints on the
+ -- monad used to build the representation are propagated when using nested
+ -- splices.
+ f :: (Quote m, C m) => m Exp
+ f = [| 5 | ]
+
+ -- f is used in a nested splice so the constraint on f, namely C, is propagated
+ -- to a constraint on the whole representation.
+ g :: (Quote m, C m) => m Exp
+ g = [| $f + $f |]
+
+ Remember, a top-level splice still requires its argument to be of type ``Q Exp``.
+ So then splicing in ``g`` will cause ``m`` to be instantiated to ``Q``::
+
+ h :: Int
+ h = $(g) -- m ~ Q
+
+
+- A *typed* expression splice is written ``$$x``, where ``x`` is
+ is an arbitrary expression.
+
+ A top-level typed expression splice can occur in place of an expression; the
+ spliced expression must have type ``Q (TExp a)``
+
+- A *typed* expression quotation is written as ``[|| ... ||]``, or
+ ``[e|| ... ||]``, where the "..." is an expression; if the "..."
+ expression has type ``a``, then the quotation has type
+ ``Quote m => m (TExp a)``.
+
+ Values of type ``TExp a`` may be converted to values of type ``Exp``
+ using the function ``unType :: TExp a -> Exp``.
+
+- A quasi-quotation can appear in a pattern, type, expression, or
+ declaration context and is also written in Oxford brackets:
+
+ - ``[varid| ... |]``, where the "..." is an arbitrary string; a full
+ description of the quasi-quotation facility is given in
+ :ref:`th-quasiquotation`.
+
+- A name can be quoted with either one or two prefix single quotes:
+
+ - ``'f`` has type ``Name``, and names the function ``f``. Similarly
+ ``'C`` has type ``Name`` and names the data constructor ``C``. In
+ general ``'``\ ⟨thing⟩ interprets ⟨thing⟩ in an expression
+ context.
+
+ A name whose second character is a single quote (sadly) cannot be
+ quoted in this way, because it will be parsed instead as a quoted
+ character. For example, if the function is called ``f'7`` (which
+ is a legal Haskell identifier), an attempt to quote it as ``'f'7``
+ would be parsed as the character literal ``'f'`` followed by the
+ numeric literal ``7``. There is no current escape mechanism in
+ this (unusual) situation.
+
+ - ``''T`` has type ``Name``, and names the type constructor ``T``.
+ That is, ``''``\ ⟨thing⟩ interprets ⟨thing⟩ in a type context.
+
+ These ``Names`` can be used to construct Template Haskell
+ expressions, patterns, declarations etc. They may also be given as an
+ argument to the ``reify`` function.
+
+- It is possible for a splice to expand to an expression that contain
+ names which are not in scope at the site of the splice. As an
+ example, consider the following code: ::
+
+ module Bar where
+
+ import Language.Haskell.TH
+
+ add1 :: Quote m => Int -> m Exp
+ add1 x = [| x + 1 |]
+
+ Now consider a splice using ``add1`` in a separate
+ module: ::
+
+ module Foo where
+
+ import Bar
+
+ two :: Int
+ two = $(add1 1)
+
+ Template Haskell cannot know what the argument to ``add1`` will be at the
+ function's definition site, so a lifting mechanism is used to promote
+ ``x`` into a value of type ``Quote m => m Exp``. This functionality is exposed to the
+ user as the ``Lift`` typeclass in the ``Language.Haskell.TH.Syntax``
+ module. If a type has a ``Lift`` instance, then any of its values can be
+ lifted to a Template Haskell expression: ::
+
+ class Lift t where
+ lift :: Quote m => t -> m Exp
+ liftTyped :: Quote m => t -> m (TExp t)
+
+ In general, if GHC sees an expression within Oxford brackets (e.g., ``[|
+ foo bar |]``, then GHC looks up each name within the brackets. If a name
+ is global (e.g., suppose ``foo`` comes from an import or a top-level
+ declaration), then the fully qualified name is used directly in the
+ quotation. If the name is local (e.g., suppose ``bar`` is bound locally in
+ the function definition ``mkFoo bar = [| foo bar |]``), then GHC uses
+ ``lift`` on it (so GHC pretends ``[| foo bar |]`` actually contains ``[|
+ foo $(lift bar) |]``). Local names, which are not in scope at splice
+ locations, are actually evaluated when the quotation is processed.
+
+ The ``template-haskell`` library provides ``Lift`` instances for many
+ common data types. Furthermore, it is possible to derive ``Lift``
+ instances automatically by using the :extension:`DeriveLift` language extension.
+ See :ref:`deriving-lift` for more information.
+
+- You may omit the ``$(...)`` in a top-level declaration splice. Simply
+ writing an expression (rather than a declaration) implies a splice.
+ For example, you can write ::
+
+ module Foo where
+ import Bar
+
+ f x = x
+
+ $(deriveStuff 'f) -- Uses the $(...) notation
+
+ g y = y+1
+
+ deriveStuff 'g -- Omits the $(...)
+
+ h z = z-1
+
+ This abbreviation makes top-level declaration slices quieter and less
+ intimidating.
+
+- Pattern splices introduce variable binders but scoping of variables in
+ expressions inside the pattern's scope is only checked when a splice is
+ run. Note that pattern splices that occur outside of any quotation
+ brackets are run at compile time. Pattern splices occurring inside a
+ quotation bracket are *not* run at compile time; they are run when the
+ bracket is spliced in, sometime later. For example, ::
+
+ mkPat :: Quote m => m Pat
+ mkPat = [p| (x, y) |]
+
+ -- in another module:
+ foo :: (Char, String) -> String
+ foo $(mkPat) = x : z
+
+ bar :: Quote m => m Exp
+ bar = [| \ $(mkPat) -> x : w |]
+
+ will fail with ``z`` being out of scope in the definition of ``foo`` but it
+ will *not* fail with ``w`` being out of scope in the definition of ``bar``.
+ That will only happen when ``bar`` is spliced.
+
+- A pattern quasiquoter *may* generate binders that scope over the
+ right-hand side of a definition because these binders are in scope
+ lexically. For example, given a quasiquoter ``haskell`` that parses
+ Haskell, in the following code, the ``y`` in the right-hand side of
+ ``f`` refers to the ``y`` bound by the ``haskell`` pattern
+ quasiquoter, *not* the top-level ``y = 7``. ::
+
+ y :: Int
+ y = 7
+
+ f :: Int -> Int -> Int
+ f n = \ [haskell|y|] -> y+n
+
+- Top-level declaration splices break up a source file into
+ *declaration groups*. A *declaration group* is the group of
+ declarations created by a top-level declaration splice, plus those
+ following it, down to but not including the next top-level
+ declaration splice. N.B. only top-level splices delimit declaration
+ groups, not expression splices. The first declaration group in a module
+ includes all top-level definitions down to but not including the first
+ top-level declaration splice.
+
+ Each declaration group is mutually recursive only within the group.
+ Declaration groups can refer to definitions within previous groups,
+ but not later ones.
+
+ Accordingly, the type environment seen by ``reify`` includes all the
+ top-level declarations up to the end of the immediately preceding
+ declaration group, but no more.
+
+ Unlike normal declaration splices, declaration quasiquoters do not
+ cause a break. These quasiquoters are expanded before the rest of the
+ declaration group is processed, and the declarations they generate
+ are merged into the surrounding declaration group. Consequently, the
+ type environment seen by ``reify`` from a declaration quasiquoter
+ will not include anything from the quasiquoter's declaration group.
+
+ Concretely, consider the following code ::
+
+ module M where
+
+ import ...
+
+ f x = x
+
+ $(th1 4)
+
+ h y = k y y $(blah1)
+
+ [qq|blah|]
+
+ k x y z = x + y + z
+
+ $(th2 10)
+
+ w z = $(blah2)
+
+ In this example, a ``reify`` inside...
+
+ 1. The splice ``$(th1 ...)`` would see the definition of ``f`` - the
+ splice is top-level and thus all definitions in the previous
+ declaration group are visible (that is, all definitions in the module
+ up-to, but not including, the splice itself).
+
+ 2. The splice ``$(blah1)`` cannot refer to the function ``w`` - ``w`` is
+ part of a later declaration group, and thus invisible, similarly,
+ ``$(blah1)`` cannot see the definition of ``h`` (since it is part of
+ the same declaration group as ``$(blah1)``. However, the splice
+ ``$(blah1)`` can see the definition of ``f`` (since it is in the
+ immediately preceding declaration group).
+
+ 3. The splice ``$(th2 ...)`` would see the definition of ``f``, all the
+ bindings created by ``$(th1 ...)``, the definition of ``h`` and all
+ bindings created by ``[qq|blah|]`` (they are all in previous
+ declaration groups).
+
+ 4. The body of ``h`` *can* refer to the function ``k`` appearing on the
+ other side of the declaration quasiquoter, as quasiquoters do not
+ cause a declaration group to be broken up.
+
+ 5. The ``qq`` quasiquoter would be able to see the definition of ``f``
+ from the preceding declaration group, but not the definitions of
+ ``h`` or ``k``, or any definitions from subsequent declaration
+ groups.
+
+ 6. The splice ``$(blah2)`` would see the same definitions as the splice
+ ``$(th2 ...)`` (but *not* any bindings it creates).
+
+ Note that since an expression splice is unable to refer to declarations
+ in the same declaration group, we can introduce a top-level (empty)
+ splice to break up the declaration group ::
+
+ module M where
+
+ data D = C1 | C2
+
+ f1 = $(th1 ...)
+
+ $(return [])
+
+ f2 = $(th2 ...)
+
+ Here
+
+ 1. The splice ``$(th1 ...)`` *cannot* refer to ``D`` - it is in the same
+ declaration group.
+ 2. The declaration group containing ``D`` is terminated by the empty
+ top-level declaration splice ``$(return [])`` (recall, ``Q`` is a
+ Monad, so we may simply ``return`` the empty list of declarations).
+ 3. Since the declaration group containing ``D`` is in the previous
+ declaration group, the splice ``$(th2 ...)`` *can* refer to ``D``.
+
+- Expression quotations accept most Haskell language constructs.
+ However, there are some GHC-specific extensions which expression
+ quotations currently do not support, including
+
+ - Recursive ``do``-statements (see :ghc-ticket:`1262`)
+
+ - Type holes in typed splices (see :ghc-ticket:`10945` and
+ :ghc-ticket:`10946`)
+
+(Compared to the original paper, there are many differences of detail.
+The syntax for a declaration splice uses "``$``" not "``splice``". The type of
+the enclosed expression must be ``Quote m => m [Dec]``, not ``[Q Dec]``. Typed expression
+splices and quotations are supported.)
+
+.. ghc-flag:: -fenable-th-splice-warnings
+ :shortdesc: Generate warnings for Template Haskell splices
+ :type: dynamic
+ :reverse: -fno-enable-th-splices
+ :category: warnings
+
+ Template Haskell splices won't be checked for warnings, because the code
+ causing the warning might originate from a third-party library and possibly
+ was not written by the user. If you want to have warnings for splices
+ anyway, pass :ghc-flag:`-fenable-th-splice-warnings`.
+
+.. _th-usage:
+
+Using Template Haskell
+----------------------
+
+- The data types and monadic constructor functions for Template Haskell
+ are in the library ``Language.Haskell.TH.Syntax``.
+
+- You can only run a function at compile time if it is imported from
+ another module. That is, you can't define a function in a module, and
+ call it from within a splice in the same module. (It would make sense
+ to do so, but it's hard to implement.)
+
+- You can only run a function at compile time if it is imported from
+ another module *that is not part of a mutually-recursive group of
+ modules that includes the module currently being compiled*.
+ Furthermore, all of the modules of the mutually-recursive group must
+ be reachable by non-SOURCE imports from the module where the splice
+ is to be run.
+
+ For example, when compiling module A, you can only run Template
+ Haskell functions imported from B if B does not import A (directly or
+ indirectly). The reason should be clear: to run B we must compile and
+ run A, but we are currently type-checking A.
+
+- If you are building GHC from source, you need at least a stage-2
+ bootstrap compiler to run Template Haskell splices and quasi-quotes.
+ A stage-1 compiler will only accept regular quotes of Haskell.
+ Reason: TH splices and quasi-quotes compile and run a program, and
+ then looks at the result. So it's important that the program it
+ compiles produces results whose representations are identical to
+ those of the compiler itself.
+
+Template Haskell works in any mode (:ghc-flag:`--make`,
+:ghc-flag:`--interactive`, or file-at-a-time). There used to be a restriction to
+the former two, but that restriction has been lifted.
+
+.. _th-view-gen-code:
+
+Viewing Template Haskell generated code
+---------------------------------------
+
+The flag :ghc-flag:`-ddump-splices` shows the expansion of all top-level
+declaration splices, both typed and untyped, as they happen. As with all
+dump flags, the default is for this output to be sent to stdout. For a
+non-trivial program, you may be interested in combining this with the
+:ghc-flag:`-ddump-to-file` flag (see :ref:`dumping-output`. For each file using
+Template Haskell, this will show the output in a ``.dump-splices`` file.
+
+The flag :ghc-flag:`-dth-dec-file` dumps the expansions of all top-level
+TH declaration splices, both typed and untyped, in the file :file:`M.th.hs`
+for each module `M` being compiled. Note that other types of
+splices (expressions, types, and patterns) are not shown. Application
+developers can check this into their repository so that they can grep for
+identifiers that were defined in Template Haskell. This is similar to using
+:ghc-flag:`-ddump-to-file` with :ghc-flag:`-ddump-splices` but it always
+generates a file instead of being coupled to :ghc-flag:`-ddump-to-file`. The
+format is also different: it does not show code from the original file, instead
+it only shows generated code and has a comment for the splice location of the
+original file.
+
+Below is a sample output of :ghc-flag:`-ddump-splices` ::
+
+ TH_pragma.hs:(6,4)-(8,26): Splicing declarations
+ [d| foo :: Int -> Int
+ foo x = x + 1 |]
+ ======>
+ foo :: Int -> Int
+ foo x = (x + 1)
+
+Below is the output of the same sample using :ghc-flag:`-dth-dec-file` ::
+
+ -- TH_pragma.hs:(6,4)-(8,26): Splicing declarations
+ foo :: Int -> Int
+ foo x = (x + 1)
+
+.. _th-example:
+
+A Template Haskell Worked Example
+---------------------------------
+
+To help you get over the confidence barrier, try out this skeletal
+worked example. First cut and paste the two modules below into :file:`Main.hs`
+and :file:`Printf.hs`:
+
+::
+
+
+ {- Main.hs -}
+ module Main where
+
+ -- Import our template "pr"
+ import Printf ( pr )
+
+ -- The splice operator $ takes the Haskell source code
+ -- generated at compile time by "pr" and splices it into
+ -- the argument of "putStrLn".
+ main = putStrLn ( $(pr "Hello") )
+
+
+ {- Printf.hs -}
+ module Printf where
+
+ -- Skeletal printf from the paper.
+ -- It needs to be in a separate module to the one where
+ -- you intend to use it.
+
+ -- Import some Template Haskell syntax
+ import Language.Haskell.TH
+
+ -- Describe a format string
+ data Format = D | S | L String
+
+ -- Parse a format string. This is left largely to you
+ -- as we are here interested in building our first ever
+ -- Template Haskell program and not in building printf.
+ parse :: String -> [Format]
+ parse s = [ L s ]
+
+ -- Generate Haskell source code from a parsed representation
+ -- of the format string. This code will be spliced into
+ -- the module which calls "pr", at compile time.
+ gen :: Quote m => [Format] -> m Exp
+ gen [D] = [| \n -> show n |]
+ gen [S] = [| \s -> s |]
+ gen [L s] = stringE s
+
+ -- Here we generate the Haskell code for the splice
+ -- from an input format string.
+ pr :: Quote m => String -> m Exp
+ pr s = gen (parse s)
+
+Now run the compiler,
+
+.. code-block:: none
+
+ $ ghc --make -XTemplateHaskell main.hs -o main
+
+Run :file:`main` and here is your output:
+
+.. code-block:: none
+
+ $ ./main
+ Hello
+
+.. _th-profiling:
+
+Using Template Haskell with Profiling
+-------------------------------------
+
+.. index::
+ single: profiling; with Template Haskell
+
+Template Haskell relies on GHC's built-in bytecode compiler and
+interpreter to run the splice expressions. The bytecode interpreter runs
+the compiled expression on top of the same runtime on which GHC itself
+is running; this means that the compiled code referred to by the
+interpreted expression must be compatible with this runtime, and in
+particular this means that object code that is compiled for profiling
+*cannot* be loaded and used by a splice expression, because profiled
+object code is only compatible with the profiling version of the
+runtime.
+
+This causes difficulties if you have a multi-module program containing
+Template Haskell code and you need to compile it for profiling, because
+GHC cannot load the profiled object code and use it when executing the
+splices.
+
+Fortunately GHC provides two workarounds.
+
+The first option is to compile the program twice:
+
+1. Compile the program or library first the normal way, without
+ :ghc-flag:`-prof`.
+
+2. Then compile it again with :ghc-flag:`-prof`, and additionally use ``-osuf
+ p_o`` to name the object files differently (you can choose any suffix that
+ isn't the normal object suffix here). GHC will automatically load the object
+ files built in the first step when executing splice expressions. If you omit
+ the :ghc-flag:`-osuf ⟨suffix⟩` flag when building with :ghc-flag:`-prof` and
+ Template Haskell is used, GHC will emit an error message.
+
+ .. index::
+ single : -osuf; using with profiling
+
+The second option is to add the flag :ghc-flag:`-fexternal-interpreter` (see
+:ref:`external-interpreter`), which runs the interpreter in a separate
+process, wherein it can load and run the profiled code directly.
+There's no need to compile the code twice, just add
+:ghc-flag:`-fexternal-interpreter` and it should just work. (this option is
+experimental in GHC 8.0.x, but it may become the default in future
+releases).
+
+.. _th-quasiquotation:
+
+Template Haskell Quasi-quotation
+--------------------------------
+
+.. extension:: QuasiQuotes
+ :shortdesc: Enable quasiquotation.
+
+ :since: 6.10.1
+
+ Enable Template Haskell Quasi-quotation syntax.
+
+Quasi-quotation allows patterns and expressions to be written using
+programmer-defined concrete syntax; the motivation behind the extension
+and several examples are documented in "`Why It's Nice to be Quoted:
+Quasiquoting for
+Haskell <http://www.cs.tufts.edu/comp/150FP/archive/geoff-mainland/quasiquoting.pdf>`__"
+(Proc Haskell Workshop 2007). The example below shows how to write a
+quasiquoter for a simple expression language.
+
+Here are the salient features
+
+- A quasi-quote has the form ``[quoter| string |]``.
+
+ - The ⟨quoter⟩ must be the name of an imported quoter, either
+ qualified or unqualified; it cannot be an arbitrary expression.
+
+ - The ⟨quoter⟩ cannot be "``e``", "``t``", "``d``", or "``p``",
+ since those overlap with Template Haskell quotations.
+
+ - There must be no spaces in the token ``[quoter|``.
+
+ - The quoted ⟨string⟩ can be arbitrary, and may contain newlines.
+
+ - The quoted ⟨string⟩ finishes at the first occurrence of the
+ two-character sequence ``"|]"``. Absolutely no escaping is
+ performed. If you want to embed that character sequence in the
+ string, you must invent your own escape convention (such as, say,
+ using the string ``"|~]"`` instead), and make your quoter function
+ interpret ``"|~]"`` as ``"|]"``. One way to implement this is to
+ compose your quoter with a pre-processing pass to perform your
+ escape conversion. See the discussion in :ghc-ticket:`5348` for details.
+
+- A quasiquote may appear in place of
+
+ - An expression
+
+ - A pattern
+
+ - A type
+
+ - A top-level declaration
+
+ (Only the first two are described in the paper.)
+
+- A quoter is a value of type
+ ``Language.Haskell.TH.Quote.QuasiQuoter``, which is defined thus: ::
+
+ data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp,
+ quotePat :: String -> Q Pat,
+ quoteType :: String -> Q Type,
+ quoteDec :: String -> Q [Dec] }
+
+ That is, a quoter is a tuple of four parsers, one for each of the
+ contexts in which a quasi-quote can occur.
+
+- A quasi-quote is expanded by applying the appropriate parser to the
+ string enclosed by the Oxford brackets. The context of the
+ quasi-quote (expression, pattern, type, declaration) determines which
+ of the parsers is called.
+
+- Unlike normal declaration splices of the form ``$(...)``, declaration
+ quasi-quotes do not cause a declaration group break. See
+ :ref:`th-syntax` for more information.
+
+.. _quasi-quotes-list-comprehension-ambiguity:
+
+.. warning::
+
+ .. index::
+ single: quasi-quotes; ambiguity with list comprehensions
+ single: list comprehensions; ambiguity with quasi-quotes
+
+ :extension:`QuasiQuotes` introduces an unfortunate ambiguity with list
+ comprehension syntax. Consider the following, ::
+
+ let x = [v| v <- [0..10]]
+
+ Without :extension:`QuasiQuotes` this is parsed as a list comprehension.
+ With :extension:`QuasiQuotes` this is parsed as a quasi-quote; however,
+ this parse will fail due to the lack of a closing ``|]``. See
+ :ghc-ticket:`11679`.
+
+The example below shows quasi-quotation in action. The quoter ``expr``
+is bound to a value of type ``QuasiQuoter`` defined in module ``Expr``.
+The example makes use of an antiquoted variable ``n``, indicated by the
+syntax ``'int:n`` (this syntax for anti-quotation was defined by the
+parser's author, *not* by GHC). This binds ``n`` to the integer value
+argument of the constructor ``IntExpr`` when pattern matching. Please
+see the referenced paper for further details regarding anti-quotation as
+well as the description of a technique that uses SYB to leverage a
+single parser of type ``String -> a`` to generate both an expression
+parser that returns a value of type ``Q Exp`` and a pattern parser that
+returns a value of type ``Q Pat``.
+
+Quasiquoters must obey the same stage restrictions as Template Haskell,
+e.g., in the example, ``expr`` cannot be defined in ``Main.hs`` where it
+is used, but must be imported.
+
+::
+
+ {- ------------- file Main.hs --------------- -}
+ module Main where
+
+ import Expr
+
+ main :: IO ()
+ main = do { print $ eval [expr|1 + 2|]
+ ; case IntExpr 1 of
+ { [expr|'int:n|] -> print n
+ ; _ -> return ()
+ }
+ }
+
+
+ {- ------------- file Expr.hs --------------- -}
+ module Expr where
+
+ import qualified Language.Haskell.TH as TH
+ import Language.Haskell.TH.Quote
+
+ data Expr = IntExpr Integer
+ | AntiIntExpr String
+ | BinopExpr BinOp Expr Expr
+ | AntiExpr String
+ deriving(Show, Typeable, Data)
+
+ data BinOp = AddOp
+ | SubOp
+ | MulOp
+ | DivOp
+ deriving(Show, Typeable, Data)
+
+ eval :: Expr -> Integer
+ eval (IntExpr n) = n
+ eval (BinopExpr op x y) = (opToFun op) (eval x) (eval y)
+ where
+ opToFun AddOp = (+)
+ opToFun SubOp = (-)
+ opToFun MulOp = (*)
+ opToFun DivOp = div
+
+ expr = QuasiQuoter { quoteExp = parseExprExp, quotePat = parseExprPat }
+
+ -- Parse an Expr, returning its representation as
+ -- either a Q Exp or a Q Pat. See the referenced paper
+ -- for how to use SYB to do this by writing a single
+ -- parser of type String -> Expr instead of two
+ -- separate parsers.
+
+ parseExprExp :: String -> Q Exp
+ parseExprExp ...
+
+ parseExprPat :: String -> Q Pat
+ parseExprPat ...
+
+Now run the compiler:
+
+.. code-block:: none
+
+ $ ghc --make -XQuasiQuotes Main.hs -o main
+
+Run "main" and here is your output:
+
+.. code-block:: none
+
+ $ ./main
+ 3
+ 1
+
+