所以我有一棵树,我想在节点类型的地方折叠
data Node = Node1 Node | Node2 Node Node | ... deriving Data
除了少数特殊情况。我想做一些事情
collapse SPECIALCASE1 = ...
collapse SPECIALCASE2 = ...
...
collapse node = foldl (++) $ gmapQ validate node
其中所有特殊情况都会生成最后一个情况只是递归折叠的结果列表;但这不起作用,因为作为 gmapQ 的第一个参数的函数必须是类型forall d. Data d => d -> u
而不是Node -> u
,据我所知,这只会限制您仅使用对该Data
类型进行操作的函数。
有没有办法强制问题中的值是正确的类型,或者可能是另一个更宽松的 map 函数?
额外信息:
上述函数的实际代码collapse
命名为validate
,用于在抽象语法树(对于非常简单的语言)中遍历和查找未绑定的变量,特殊情况的处理方式如下
validate _ (Nr _) = []
validate env (Let var val expr) = validate env val ++ validate (var:env) expr
validate env (Var var) = if elem var env then [] else [var]
这本质上是文字数字中没有变量的规则,让表达式绑定一个变量,并且需要检查变量是否绑定。这种玩具语言中的所有其他构造只是数字和变量的组合(例如求和、乘法等),因此当我检查未绑定的变量时,我只需要遍历它们的子树并组合结果;因此gmapQ
.
额外信息2:
Node
代替上面示例的实际数据类型为
data Ast = Nr Int
| Sum Ast Ast
| Mul Ast Ast
| Min Ast
| If Ast Ast Ast
| Let String Ast Ast
| Var String
deriving (Show, Eq, Data)