我有一个已定义的数据类型
datatype expression = Constant of int
| Variable of string
| Operator of string * expression
| Pair of expression list
| List of expression list
我得到了两个有以下形式的分数:
Operator("/", Pair [Constant x, Constant y])
或
Operator("/", Pair [Variable x, Constant y])
我需要将这两个分数相加并返回一个新的表达式,它将两个分母中最小公倍数作为分母。
我设法让它工作,但我的代码似乎不必要地复杂和复杂。有没有办法写这个更短?
到目前为止我做了什么:
fun add (a,b) =
case (a,b) of
(Operator("/", Pair [Constant x1, Constant y1]),
Operator("/", Pair [Constant x2, Constant y2]))
=> Operator("/", Pair [Constant ((x1*((lcm(y1,y2) div y1)))+(x2*(lcm(y1,y2) div y2))), Constant (lcm(y1,y2))])
| (Operator("/", Pair [Variable x1, Constant y1]),
Operator("/", Pair [Constant x2, Constant y2 ]))
=> Operator("/", Pair[
Operator("+", Pair[
Operator("*", Pair[Variable x1, Constant (lcm(y1,y2) div y1)]),
Constant (x2* (lcm(y1,y2) div y2)) ]),
Constant (lcm(y1,y2))])
| (Operator("/", Pair [Constant x1, Constant y1]),
Operator("/", Pair [Variable x2, Constant y2 ]))
=> Operator("/", Pair[
Operator("+", Pair[
Operator("*", Pair[Variable x2, Constant (lcm(y1,y2) div y2)]),
Constant (x1* (lcm(y1,y2) div y2)) ]),
Constant (lcm(y1,y2))])
| (Operator("/", Pair [Variable x1, Constant y1]),
Operator("/", Pair [Variable x2, Constant y2 ]))
=> Operator("/", Pair[
Operator("+", Pair[
Operator("*", Pair[Variable x1, Constant (lcm(y1,y2) div y1)]),
Operator("*", Pair[Variable x2, Constant (lcm(y1,y2) div y2)])]),
Constant (lcm(y1,y2))])
答案 0 :(得分:4)
有没有办法把它写得更短?
是。瞄准最简单的模式。例如。如果要构建抽象语法树,
fun add (e1, e2) = Operator ("+", Pair [e1, e2])
如果您正在评估语法树,
fun eval env exp =
case exp of
Constant i => i
| Variable x => lookup x env
| Operator (oper, exps) => evalOp env oper (map (eval env) exps)
| ... => ???
and evalOp env "+" is = foldl op+ 0 is
| evalOp env "-" is = foldl op- 0 is
| ...
特别是:您可能想重新考虑对和列表可以评估的有意义的标量值,以及是否应该将对和列表限制为语法树的某些部分。
通常:每当您的模式更深层匹配一个级别时,匹配个案的数量乘以构造函数的数量。一个或两个匹配级别通常就足够了。如果没有,编写执行更深匹配的辅助函数几乎总是理所当然的选择。