diff options
author | Matthew Pickering <matthewtpickering@gmail.com> | 2020-05-26 13:31:13 +0100 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2020-07-21 14:47:19 -0400 |
commit | a625719284db7c69fa3d122e829291a16960e85f (patch) | |
tree | b15fb36d401ea100a93ec9baec4c6b8c36adffba /docs | |
parent | 05910be1ac5c1f485132d2c8bd1ceb4f86e06db5 (diff) | |
download | haskell-a625719284db7c69fa3d122e829291a16960e85f.tar.gz |
Use a newtype `Code` for the return type of typed quotations (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')
-rw-r--r-- | docs/users_guide/exts/deriving_extra.rst | 2 | ||||
-rw-r--r-- | docs/users_guide/exts/template_haskell.rst | 10 |
2 files changed, 6 insertions, 6 deletions
diff --git a/docs/users_guide/exts/deriving_extra.rst b/docs/users_guide/exts/deriving_extra.rst index 1352170af7..e1d63c4b65 100644 --- a/docs/users_guide/exts/deriving_extra.rst +++ b/docs/users_guide/exts/deriving_extra.rst @@ -528,7 +528,7 @@ Deriving ``Lift`` instances The class ``Lift``, unlike other derivable classes, lives in ``template-haskell`` instead of ``base``. Having a data type be an instance of ``Lift`` permits its values to be promoted to Template Haskell expressions (of -type ``ExpQ`` and ``TExpQ a``), which can then be spliced into Haskell source +type ``ExpQ`` and ``Code Q a``), which can then be spliced into Haskell source code. Here is an example of how one can derive ``Lift``: 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 |