Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
遍历Haskell AST模板_Haskell_Template Haskell - Fatal编程技术网

遍历Haskell AST模板

遍历Haskell AST模板,haskell,template-haskell,Haskell,Template Haskell,我已经了解到,模板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 traversa

我已经了解到,
模板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'
     

现在我越来越相信这样写,除了费时,也是浪费,因为遍历/转换AST是常见的做法,我想最好问问从业者中有什么可用的解决方案。

一般来说,我不确定通用的TH遍历是否会经常出现。(我正在努力想象一个有用的转换,在这种情况下,你不会仅仅生成已经转换过的TH。)我猜在某些情况下,你想执行用户提供的准字节的查询或转换,而不解析整个AST

无论如何,如果你能找到它的用途,你可以使用SYB泛型。例如,这里有一个查询,用于从任意TH“thing”的模式和表达式中提取文本:

{-#语言模板haskell}
导入数据。泛型
导入语言.Haskell.TH
getLiterals::数据d=>d->[Lit]
getLiterals=everything(++)(mkQ[]litE`extQ`litP)
其中litE(litE l)=[l]
litE=[]
litP(litP l)=[l]
litP[uU9=[]

main=do mydec关于您的问题,即在已经有效的TH AST上执行转换的动机,我可以想到引用的DSL,它将宿主语言中的一元理解转换为SQL查询,例如我们已经使用Microsoft LINQ。这不合理吗?
{-# 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
{-# 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 mydec