haskell ghc pretty-print template-haskell

Método preferido para ver el código generado por Template Haskell



ghc pretty-print (3)

¿Está buscando el -ddump-splices para el compilador?

Como usted sabe, Template Haskell se usa para generar varios tipos de empalmes AST programáticamente en tiempo de compilación.

Sin embargo, un empalme a menudo puede ser muy opaco, y a menudo es difícil discernir lo que realmente genera un empalme. Si ejecuta la mónada Q para un empalme, y el empalme está bien tipado, obtendrá una representación show de la pieza generada de AST, pero esta representación puede ser muy difícil de entender, debido a su diseño no estructurado.

¿Cuál es el método preferido para convertir una pieza de AST generada por TH en algo similar al código Haskell normal, para que el código pueda leerse y comprenderse fácilmente? ¿Se puede reconstruir el código fuente de, por ejemplo, un valor dado de Dec ? ¿Hay que leer el código GHC Core? ¿Hay alguna manera de estructurar al menos el AST para que sea más legible (más allá de lo que, por ejemplo, el paquete del pretty-show )?


Como complemento a la share :

Tenga en cuenta que el uso de runQ directamente de GHCi en general podría no funcionar (por ejemplo, los generadores TH que utilizan operaciones de reificar, consulte los comentarios sobre la declaración runQ ).

Cuando eso falla, puede pprint (o show ), transformar la introducción de una cadena de caracteres stringE luego empalmar como un argumento para 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


Puede utilizar pprint o ppr desde Language.Haskell.TH.Ppr (importado automáticamente con 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

No es bonito, pero es válido Haskell. Debería poder hacer que la salida sea más agradable eliminando los prefijos de los módulos de los nombres de los Preludios (aunque es posible que tenga que tener cuidado de solo quitar el prefijo esperado; Foo.* Es un operador infijo perfectamente válido, después de todo).