Чтобы ответить на это, полезно знать, что такое квазициклер. Из GHC Documentation, квази-Quoter является значением
data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp,
quotePat :: String -> Q Pat,
quoteType :: String -> Q Type,
quoteDec :: String -> Q [Dec] }
То есть, это парсер из произвольной строки к одному или нескольким из ExpQ
, PatQ
, TypeQ
и DecQ
, которые Template Haskell представления выражений , шаблоны, типы и декларации соответственно.
Когда вы используете квазицитацию, GHC применяет синтаксический анализатор к String для создания ExpQ
(или другого типа), а затем объединяет в полученное выражение haskell шаблона для получения фактического значения.
Похоже, что вы просите сделать раздельный синтаксический анализ и сплайсинг квазиквазота, чтобы у вас был доступ к выражению TH. Затем вы можете импортировать это выражение в другой модуль и объединить его там сами.
Зная тип квазициклера, легко понять, что это возможно. Обычно вы используете QQ, как
-- file Expr.hs
eval :: Expr -> Integer
expr = QuasiQuoter { quoteExp = parseExprExp, quotePat = parseExprPat }
-- file Foo.hs
import Expr
myInt = eval [expr|1 + 2|]
Вместо этого, вы можете извлечь анализатору самостоятельно, получить TH выражение, и сращивать его позже:
-- file Foo.hs
import Expr
-- run the QQ parser
myInt_TH :: ExpQ
myInt_TH = quoteExp expr "1 + 2"
-- file Bar.hs
import Foo.hs
-- run the TH splice
myInt = $(myInt_TH)
Конечно, если вы пишете все это самостоятельно, вы можете пропустить квази-кавычки и напрямую использовать парсер и шаблон Haskell. Это почти то же самое в любом случае.
Я думаю, было бы полезно, если бы вы могли упомянуть о том, чего вы пытаетесь достичь с этим. Технически TH может запускать произвольное IO, включая чтение и анализ компилируемого модуля, чтобы вы могли извлекать материал из разных мест или даже разных модулей, но детали зависят от того, что вы пытаетесь сделать. – hammar