我正在实现一个解释器,允许用户定义任意combinators并将它们应用于任意术语。例如,用户可以通过输入以下组合子定义来定义Church encoding for pairs:
pair a b c → c a b
true a b → a
first a → a true
用户可以输入first (pair a b)
,根据之前定义的规则逐步减少:
first (pair a b)
→ pair a b true
→ true a b
→ a
也可以定义其他组合器,例如SKI combinator calculus中使用的组合器:
S x y z → x z (y z)
K x y → x
I x → x
身份组合器也可以通过I → S S K K
或I → S K (K K)
或I = S K x
根据前两个组合子来定义。然后可以通过以下方式定义通用iota combinator:
ι x → x S K
这些例子有希望说明我想要做的事情。
我正在尝试使用graph reduction和graph rewriting系统来实现此功能。设tree
为
tree = leaf | (tree tree)
这是一个二叉树,其中节点可以是由一对子树组成的叶子(终端节点)或分支(内部节点)。分支表示将术语应用于另一个术语,而叶子表示组合子和参数。设rule
为
rule = (tree tree)
这对应于将左树转换为右树(a→b)的缩减规则。然后可以通过
定义rules
列表
rules = rule | (rule rules)
实际上,在评估诸如pair a b c → c a b
之类的表达式时,解释器构造对应于左侧的(((pair a) b) c)
形式的树,与((c a) b)
对应的形式的树右侧,构造一对对应于rule
的两棵树(其中a,b,c
以某种方式被指定为任意参数,而不一定是组合符或终端符号),并将该对附加到列表{{ 1}}。在减少rules
形式的表达式时,解释器构造相应的树first (pair a b)
并应用如下的缩减规则:
(first ((pair a) b))
要做到这一点,解释器必须在树及其子树上执行模式匹配,"移动"组合器和任意参数构造对应于规则右侧的新树。
给出了C中树结构的示例实现(first ((pair a) b))
→ (((pair a) b) true)
→ ((true a) b)
→ a
模式匹配功能可以实现为
struct tree_t {
bool is_leaf;
union {
char* symbol;
struct {
tree_t* left;
tree_t* right;
};
};
};
但是,我不确定如何实施此过程的重要细节,包括:
我相信节点上的模式匹配将涉及检查节点的左子节点和右子节点,等等,直到到达终端节点。有没有人知道在C中实现了类似概念的在线程序或教程,我可以从中学到什么?我是否正在通过这种方法解决问题的正确轨道,还是有更简单的方法?
答案 0 :(得分:1)
您需要分两步完成。模式匹配器将模式与树进行匹配,并构建将模式中的变量映射到树中的值的字典。
然后将该字典传递给另一个填充替换的函数,方法是将变量替换为字典中的值。
SICP中描述的模式匹配方法在C中可以正常工作,尽管您可能会发现使用可变数据结构更容易用于字典。见https://mitpress.mit.edu/sicp/full-text/sicp/book/node99.html