虽然与宏的工作,我已经达到的地步(我一直在努力,以避免它),我需要不断更新。其中占有一定的条件AST的节点。 举例来说,假设我想更新的每个节点:
Literal(Constant(1))
与价值:
Literal(Constant(2))
这些AST节点可能是表达式树中的任何地方,所以我不能使用的ad-hoc模式匹配。 很显然,我希望做的最后一件事是编写一个完整的模式匹配器,它能够覆盖所有的编译器原语。 我一直在寻找的在API ,但我的印象中,例如收集和穿越的家人方法不够好,以满足我的需求,因为他们把树作为一个线性的事情,我想整个更新树结果。 那么,是不是可以在一个巧妙的方法来更新不可改变的表达式树? 为什么不标准的API中存在这样的“更新”操作?
下面是使用Scala的宏观的AST变压器的实例:
https://github.com/retronym/macrocosm/blob/171be7e/src/main/scala/com/github/retronym/macrocosm/Macrocosm.scala#L129
修改数据结构的聚类型的节点一般是数据类型泛型(经由类型构造的代码参数化)的一个典型例子。
有几种方法进行这样的操作,如存在“废你的样板”的办法,它定义数据类型的通用穿越功能。
在Haskell,节点更新功能参数在两个方面:通过数据类型和代码 - 这样你就可以应用不同的更新功能,以不同的类型,在任何地方的结构:
-- | Apply a transformation everywhere in bottom-up manner
everywhere :: (forall a. Data a => a -> a)
-> (forall a. Data a => a -> a)
在Haskell这样做在很大程度上依赖于类型的类。 在Scala中,有几个端口的例子