This text is a translation of the Template Haskell documentation written by Bulat Ziganshin. Translation of the entire text is divided into several logical parts to facilitate perception. Further italics in the text - notes of the translator.
yell file line = fail ($(printf "Error in file %s line %d") file line)
yell file line = fail ((\x1 x2 -> "Error in file "++x1++" line "++show x2) file line)
data T = A Int String | B Integer | C $(deriveShow ''T)
data T = A Int String | B Integer | C instance Show T show (A x1 x2) = "A "++show x1++" "++show x2 show (B x1) = "B "++show x1 show C = "C"
Exp
type for expressions, Pat
for samples, Lit
for literals, Dec
for declarations, Type
for types, etc. Definitions of all these types can be found in the documentation for the Language.Haskell.TH.Syntax
module. They are interconnected according to Haskell syntax rules, so using them you can construct values ββrepresenting any Haskell code fragments. Here are some simple examples: varx = VarE (mkName "x")
represents the expression x
, i.e. simple variable β x
β patx = VarP (mkName "x")
represents sample x
, i.e. the same variable β x
β used in the sample str = LitE (StringL "str")
represents the constant expression "str"
tuple = TupE [varx, str]
represents a pair expression (tuple) (x,"str")
LamE [patx] tuple
represents the lambda expression \x -> (x,"str")
Exp
type constructors end with E
, the names of Pat
-type constructors end with P
, etc. The mkName
function used above creates a value of type Name
(representing identifiers) from a normal string ( String
), with its contents as a name.Exp
(you can also use Dec
, Pat
or Type
) , which is a representation for a given code fragment. In fact, you do not need to thoroughly study the device of these types in order to know how to submit the Haskell code you need into them. In the section on debugging, I will tell you how to get a TH-representation of a specific Haskell code fragment.Exp
. Instead, they are calculations in a special Q
monad (called the qadtation monad citation monad), which allows you to automatically generate unique names for variables using the monadic function newName
:: String -> Q Name
. Each time it is called, a new unique name is generated with the given prefix. This name can be used as part of a pattern (using the constructor VarP
:: Name -> Pat
) or an expression ( VarE
:: Name -> Exp
).tupleReplicate
template, which, when used as follows: β$(tupleReplicate n) x"
, returns an n-tuple with x
at all positions (similar to the replicate
function for lists). Note that n
Is the template argument, and x
is the argument of the generated anonymous function (lambda expression). I provide the code for the module containing the definition of this template (the Language.Haskell.TH
module provides all the tools needed for working with TH): module TupleReplicate where import Language.Haskell.TH tupleReplicate :: Int -> Q Exp tupleReplicate n = do id <- newName "x" return $ LamE [VarP id] (TupE $ replicate n $ VarE id)
tupleReplicate 3
β will return an Exp
value equivalent to the Haskell expression β (\x -> (x,x,x))
β.$x
β, where x
is an identifier, or in the form of $(...)
, where the ellipsis implies the corresponding expression. It is important that there is no space between the $
character and the identifier or brackets. This use of $
overrides the value of this symbol as an infix operator, as well as the qualified name Mx
overrides the value of the function composition operator β .
". If you need an operator, then the character must be surrounded by spaces.Q Exp
.Q [Dec]
. Ads generated by the insert have access only to those identifiers that were previously declared in the code (which is not typical of regular Haskell programs, in which the order of ads does not matter).Q Type
.-XTemplateHakell
flag to enable the special TH syntax; or you can include the directive {-# LANGUAGE TemplateHaskell #-}
in the source code.tupleReplicate
template: {-# LANGUAGE TemplateHaskell #-} module Test where import TupleReplicate main = do print ($(tupleReplicate 2) 1) -- (1,1) print ($(tupleReplicate 5) "x") -- ("x","x","x","x","x")
printf
and deriveShow
mentioned at the beginning are deriveShow
.Source: https://habr.com/ru/post/131998/
All Articles