summaryrefslogtreecommitdiff
path: root/docs/users_guide/exts/template_haskell.rst
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2020-05-26 13:31:13 +0100
committerSylvain Henry <sylvain@haskus.fr>2020-07-21 08:48:20 +0200
commite2d5d80d24a931e5351e64017694ab8aa84c6c1d (patch)
treebaaec48b1c9c47a1308eb1cb6757c86ef54ee4ef /docs/users_guide/exts/template_haskell.rst
parentc26e81d116a653b5259aeb290fb1e697efe3382a (diff)
downloadhaskell-wip/proposal-195.tar.gz
Use a newtype `Code` for the return type of typed quotations (Proposal #195)wip/proposal-195
There are three problems with the current API: 1. It is hard to properly write instances for ``Quote m => m (TExp a)`` as the type is the composition of two type constructors. Doing so in your program involves making your own newtype and doing a lot of wrapping/unwrapping. For example, if I want to create a language which I can either run immediately or generate code from I could write the following with the new API. :: class Lang r where _int :: Int -> r Int _if :: r Bool -> r a -> r a -> r a instance Lang Identity where _int = Identity _if (Identity b) (Identity t) (Identity f) = Identity (if b then t else f) instance Quote m => Lang (Code m) where _int = liftTyped _if cb ct cf = [|| if $$cb then $$ct else $$cf ||] 2. When doing code generation it is common to want to store code fragments in a map. When doing typed code generation, these code fragments contain a type index so it is desirable to store them in one of the parameterised map data types such as ``DMap`` from ``dependent-map`` or ``MapF`` from ``parameterized-utils``. :: compiler :: Env -> AST a -> Code Q a data AST a where ... data Ident a = ... type Env = MapF Ident (Code Q) newtype Code m a = Code (m (TExp a)) In this example, the ``MapF`` maps an ``Ident String`` directly to a ``Code Q String``. Using one of these map types currently requires creating your own newtype and constantly wrapping every quotation and unwrapping it when using a splice. Achievable, but it creates even more syntactic noise than normal metaprogramming. 3. ``m (TExp a)`` is ugly to read and write, understanding ``Code m a`` is easier. This is a weak reason but one everyone can surely agree with. Updates text submodule.
Diffstat (limited to 'docs/users_guide/exts/template_haskell.rst')
-rw-r--r--docs/users_guide/exts/template_haskell.rst10
1 files changed, 5 insertions, 5 deletions
diff --git a/docs/users_guide/exts/template_haskell.rst b/docs/users_guide/exts/template_haskell.rst
index f1319b904e..a33949a1f1 100644
--- a/docs/users_guide/exts/template_haskell.rst
+++ b/docs/users_guide/exts/template_haskell.rst
@@ -133,15 +133,15 @@ The :extension:`TemplateHaskellQuotes` extension is considered safe under
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)``
+ spliced expression must have type ``Code Q 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)``.
+ ``Quote m => Code m a``.
- Values of type ``TExp a`` may be converted to values of type ``Exp``
- using the function ``unType :: TExp a -> Exp``.
+ It is possible to extract a value of type ``m Exp`` from ``Code m a``
+ using the ``unTypeCode :: Code m a -> m Exp`` function.
- A quasi-quotation can appear in a pattern, type, expression, or
declaration context and is also written in Oxford brackets:
@@ -202,7 +202,7 @@ The :extension:`TemplateHaskellQuotes` extension is considered safe under
class Lift t where
lift :: Quote m => t -> m Exp
- liftTyped :: Quote m => t -> m (TExp t)
+ liftTyped :: Quote m => t -> Code m 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