Подтвердить что ты не робот

Предпочтительный метод просмотра кода, созданного Template Haskell

Как вы знаете, Template Haskell используется для генерации различных видов сращиваний AST программно во время компиляции.

Однако сплайсинг часто может быть очень непрозрачным, и часто бывает трудно различить, что на самом деле создает сращивание. Если вы запустили монаду Q для сращивания, а сплайс хорошо типизирован, вы получите show возможность представления сгенерированной части АСТ, но это представление может быть очень трудно понять из-за его неструктурированной компоновки.

Каков предпочтительный метод преобразования части TH-генерируемого AST в нечто похожее на обычный код Haskell, так что код можно легко прочитать и понять? Можно ли восстановить исходный код, например. заданное значение Dec? Нужно ли читать код ядра GHC? Есть ли способ, по крайней мере, структурировать AST, чтобы он стал более читаемым (помимо того, что делает пакет pretty-show)?

4b9b3361

Ответ 1

Вы можете использовать pprint или ppr из Language.Haskell.TH.Ppr (автоматически импортируется с Language.Haskell.TH):

GHCi> expr <- runQ [| \f g x -> f (x*2 + 3) . g |]
GHCi> putStrLn $ pprint expr
\f_0 g_1 x_2 -> f_0 ((x_2 GHC.Num.* 2) GHC.Num.+ 3) GHC.Base.. g_1

Это не очень, но это действительно Haskell. Вы должны уметь сделать вывод более приятным, отделив префиксы модулей от имен Prelude (хотя вам, возможно, нужно быть осторожным, чтобы убрать только ожидаемый префикс; Foo.* - вполне действительный оператор инфикса, в конце концов).

Ответ 2

Вы ищете флаг -ddump-splices для компилятора?

Ответ 3

В качестве дополнения к ehird answer:

Обратите внимание, что использование runQ непосредственно из GHCi вообще может не работать (например: TH-генераторы, которые используют операции reify ср комментарии над объявлением runQ).

Если это не удается, вы можете pprint (или show) преобразовать int строковое выражение stringE, а затем сплайсировать в качестве аргумента putStrLn:

> putStrLn $(stringE . pprint =<< [| \f g x -> f (x*2 + 3) . g |])
\f_0 g_1 x_2 -> f_0 ((x_2 GHC.Num.* 2) GHC.Num.+ 3) GHC.Base.. g_1