首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >遍历模板Haskell AST

遍历模板Haskell AST
EN

Stack Overflow用户
提问于 2020-12-23 08:57:36
回答 1查看 107关注 0票数 3

我发现template-haskell中的Haskell代码并没有被表示为一个单独的AST,而是四种交叉引用类型:PatExpDecType。我也没有在库中发现任何遍历工具,或者其他任何地方。

我最初寻找的是上述四种类型的统一表示:

代码语言:javascript
复制
-- 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是一种常见的做法,我认为最好的做法是询问实践者中有什么可用的解决方案。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-23 11:32:22

一般来说,我不确定TH的泛型遍历可能会经常出现。(我很难想象在这样一种情况下,TH AST的有用转换,在这种情况下,您不会只生成已经以这种方式转换的TH。)我猜在某些情况下,您希望在不解析整个AST的情况下执行用户提供的准引号的查询或转换?

无论如何,如果你能找到它的用处,你可以使用SYB泛型。例如,下面的查询从模式中提取文字,并从任意的TH“事物”中提取表达式:

代码语言:javascript
复制
{-# 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的示例没有显示):

代码语言:javascript
复制
{-# 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
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65417779

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档