我发现template-haskell中的Haskell代码并没有被表示为一个单独的AST,而是四种交叉引用类型:Pat、Exp、Dec和Type。我也没有在库中发现任何遍历工具,或者其他任何地方。
我最初寻找的是上述四种类型的统一表示:
-- The single representation for Haskell code
data HCode = HE Exp | HD Dec | HP Pat | HT Type
-- And common functions in tree traversal such as:
children :: HCode -> [HCode]
children (HE (VarE _)) = []
children (HE (AppTypeE e t)) = [HE e, HT t]
children c = ...
-- Ultimately a transform function similar to:
-- (Not really arguing about this exact model of tree transformation)
preorder :: (HCode -> HCode) -> HCode -> HCode
preorder f h =
let h' = f h
in rebuildWithChildren h' . fmap (preorder f) . children $ h'现在,我越来越相信这样写它除了耗时外,还很浪费,因为遍历/转换ask是一种常见的做法,我认为最好的做法是询问实践者中有什么可用的解决方案。
发布于 2020-12-23 11:32:22
一般来说,我不确定TH的泛型遍历可能会经常出现。(我很难想象在这样一种情况下,TH AST的有用转换,在这种情况下,您不会只生成已经以这种方式转换的TH。)我猜在某些情况下,您希望在不解析整个AST的情况下执行用户提供的准引号的查询或转换?
无论如何,如果你能找到它的用处,你可以使用SYB泛型。例如,下面的查询从模式中提取文字,并从任意的TH“事物”中提取表达式:
{-# LANGUAGE TemplateHaskell #-}
import Data.Generics
import Language.Haskell.TH
getLiterals :: Data d => d -> [Lit]
getLiterals = everything (++) (mkQ [] litE `extQ` litP)
where litE (LitE l) = [l]
litE _ = []
litP (LitP l) = [l]
litP _ = []
main = do mydec <- runQ [d| foo 4 = "hello" |]
print mydec
print $ getLiterals mydec
myexp <- runQ [| '1' + "sixteen" |]
print myexp
print $ getLiterals myexp下面是一个转换,它转换模式、表达式和类型中的所有中缀操作符( InfixT的示例没有显示):
{-# LANGUAGE TemplateHaskell #-}
import Data.Generics
import Language.Haskell.TH
causeChaos :: Data d => d -> d
causeChaos = everywhere (mkT destroyExpressions `extT` manglePatterns `extT` bludgeonTypes)
where destroyExpressions (InfixE l x r) = InfixE r x l
destroyExpressions (UInfixE l x r) = UInfixE r x l
destroyExpressions e = e
manglePatterns (InfixP l x r) = InfixP r x l
manglePatterns (UInfixP l x r) = UInfixP r x l
manglePatterns e = e
bludgeonTypes (InfixT l x r) = InfixT r x l
bludgeonTypes (UInfixT l x r) = UInfixT r x l
bludgeonTypes e = e
main = do mydec <- runQ [d| append :: [a] -> [a] -> [a]
append (x:xs) ys = x : append xs ys
append [] ys = ys
|]
print mydec
print $ causeChaos mydechttps://stackoverflow.com/questions/65417779
复制相似问题