实现组合子演算

时间:2014-06-10 22:26:17

标签: functional-programming binary-tree interpreter combinators combinatory-logic

概念

我正在实现一个解释器,允许用户定义任意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 KI → S K (K K)I = S K x根据前两个组合子来定义。然后可以通过以下方式定义通用iota combinator

ι x → x S K

这些例子有希望说明我想要做的事情。

实施

我正在尝试使用graph reductiongraph 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;
        };
    };
};

但是,我不确定如何实施此过程的重要细节,包括:

  1. 将输入树与缩减规则的LHS树匹配。
  2. 将输入树转换为缩小规则的RHS树,保留参数(可以是叶子或分支)和"移动它们"到适当的地方。
  3. 我相信节点上的模式匹配将涉及检查节点的左子节点和右子节点,等等,直到到达终端节点。有没有人知道在C中实现了类似概念的在线程序或教程,我可以从中学到什么?我是否正在通过这种方法解决问题的正确轨道,还是有更简单的方法?

1 个答案:

答案 0 :(得分:1)

您需要分两步完成。模式匹配器将模式与树进行匹配,并构建将模式中的变量映射到树中的值的字典。

然后将该字典传递给另一个填充替换的函数,方法是将变量替换为字典中的值。

SICP中描述的模式匹配方法在C中可以正常工作,尽管您可能会发现使用可变数据结构更容易用于字典。见https://mitpress.mit.edu/sicp/full-text/sicp/book/node99.html