Я пытаюсь понять, как Quasi Quoter генерирует структуры TH. Итак, я пытаюсь преобразовать первый пример из Метапрограммирование шаблонов для Haskell, от формата в кавычках к просто типам.
gen :: [Format] -> ExpQ -> ExpQ
gen [] x = x
gen (D:xs) x = [| \n -> $(gen xs [| $x ++ show n |]) |]
gen (S:xs) x = [| \s -> $(gen xs [| $x ++ s |]) |]
gen (L s:xs) x = gen xs [| $x ++ $(THS.lift s) |]
gen (D:xs) x
превратится в
gen (D:xs) x = lamE [varP $ mkName "n"]
(appE (appE (varE 'gen) (varE 'xs))
(uInfixE (x) (varE '(Prelude.++))
(appE (varE 'Prelude.show) (varE $ mkName "n"))))
Однако этот фрагмент не будет компилировать ссылку на 'xs
.
GHC выдает следующую ошибку:
src/Print/Default.hs:28:51:
Stage error: the non-top-level quoted name 'xs
must be used at the same stage at which is is bound
In the Template Haskell quotation 'xs
In the first argument of `varE', namely 'xs
In the second argument of `appE', namely `(varE 'xs)'
Есть ли какой-то другой способ, которым вам нужно сослаться на имя параметра функции, чтобы Template Haskell мог его использовать?
x
локально связано, у вас не может быть$x
, но вы можете иметь[| ... $x ... |]
. Во 2-й версии вы этого не сделали, да и делать это не имеет смысла, так какlamE [varP ..]
ожидаетExpQ
, а\n ->
внутри стыка ожидаетString
. - person user2407038   schedule 03.06.2014