使用判别联盟实现基本的代数简化F#

时间:2017-05-16 20:32:37

标签: f# pattern-matching discriminated-union

我正在使用判别联盟来定义代数表达式,然后实现一个简化函数,该函数使用递归的匹配 - 案例算法执行基本的代数简化。我遇到了涉及嵌套加法/减法/乘法的障碍。

问题在于,添加/减去/ etc两个或多个嵌套Expression对象的匹配大小写一直都不会简化为单个常量。 IE:

simplify Add( Add( Const(1), Const(2) ), Add( Const(1), Const(2) ) )

返回包含Expression的{​​{1}}对象,该对象应返回包含Add(Const(3), Const(3))的对象

以下代码将使发生的事情变得非常清楚,为简洁起见,我只包括了Addition的情况,因为结构(和问题)对于减法和乘法是相同的:

Const(6)

问题是,对于当前结构化的方式,匹配// Expression type type Expression = | X | Y | Const of float | Neg of Expression | Add of Expression * Expression | Sub of Expression * Expression | Mul of Expression * Expression let rec simplify expr = match expr with | X -> expr | Y -> expr | Const(n) -> Const(n) | Add(X, Const(0.0)) -> X | Add(Const(0.0), X) -> X | Add(Const(0.0), Y) -> Y | Add(Y, Const(0.0)) -> Y | Add(Const(n1), Const(n2)) -> Const(n1+n2) // PROBLEM_1 | Add(expr1, expr2) -> Add(simplify(expr1), simplify(expr2)) // PROBLEM_2 的输入不会完全递归地简化为// PROBLEM_2个案,即使// PROBLEM_1和{{1}也是如此仅包含expr1个值。如上所述,它最终将返回包含expr2的{​​{1}},而不是实际将最后两个值添加到Const

我可以对结构的方式进行哪些更改,以便Expression在所有子表达式包含且可缩减为-> Add(Const(n2), Const(n2))值的情况下返回单个-> Const(n1+n2),即:不包含变量或不可简化的表达式?

1 个答案:

答案 0 :(得分:5)

我认为最后一行改为

| Add(expr1, expr2) -> simplify(Add(simplify(expr1), simplify(expr2)))
//                     ^^^^^^^^^                                     ^

是唯一需要改变的吗?