Итак, я начинаю экспериментировать с квазицитатами и шаблонным haskell.
Я хочу изменить существующий (большой) код квазицитирования, используя фактическое значение переменной, определенной там, где она «вызывается». Чтобы проиллюстрировать на простом примере:
main.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Exp02
x = "cde"
main = do
putStrLn [str|$x|]
Exp02.hs
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module Exp02 where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Quote
xpto :: String -> ExpQ
xpto [] = stringE []
xpto ('$':rest) = varE (mkName rest)
xpto str = stringE str
str = QuasiQuoter
{ quoteExp = xpto
, quotePat = fail $ "patterns"
, quoteType= fail $ "types"
, quoteDec = fail $ "declarations"
}
Пока это компилируется и выводит "cde", это не то, что я хочу. Насколько я понимаю, результирующий код в main после сплайсинга: putStrLn x
. Я хочу сгенерировать putStrLn cde
(я знаю, что это недействительный код haskell, но это просто для представления моей точки зрения).
Таким образом, другими словами, я не хочу "создавать ссылку на переменную x
в основном файле", я хочу фактически использовать ее значение внутри кода квазицитата xpto
.
Я предполагаю, что это может быть невозможно, поскольку это будет означать циклическую ссылку между main.hs
и Exp02.hs
и, таким образом, столкнуться с ограничением этапа TH. Это правильно или есть способ использовать x value внутри кода xpto
?
Спасибо!