将 SML 中的两个分数相加
Summing two fractions in SML
我有一个定义的数据类型
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])
我需要对这两个分数求和return一个新的表达式,它的分母是两个分母的最小公倍数。
我设法让它工作,但我的代码似乎不必要地复杂和令人费解。有没有办法把这个写得更短?
到目前为止我设法做了什么:
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))])
Is there a way to write this shorter?
是的。以尽可能简单的模式为目标。例如。如果你正在构建一个抽象语法树,
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
| ...
特别是:您可能需要重新考虑对和列表可能评估的有意义的标量值,以及是否应该将对和列表限制在语法树的某些部分.
通常:每次你的模式匹配更深一层,匹配案例的数量就会乘以构造函数的数量。一级或二级匹配通常就足够了。如果没有,编写执行更深匹配的辅助函数几乎总是明智的选择。
我有一个定义的数据类型
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])
我需要对这两个分数求和return一个新的表达式,它的分母是两个分母的最小公倍数。
我设法让它工作,但我的代码似乎不必要地复杂和令人费解。有没有办法把这个写得更短?
到目前为止我设法做了什么:
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))])
Is there a way to write this shorter?
是的。以尽可能简单的模式为目标。例如。如果你正在构建一个抽象语法树,
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
| ...
特别是:您可能需要重新考虑对和列表可能评估的有意义的标量值,以及是否应该将对和列表限制在语法树的某些部分.
通常:每次你的模式匹配更深一层,匹配案例的数量就会乘以构造函数的数量。一级或二级匹配通常就足够了。如果没有,编写执行更深匹配的辅助函数几乎总是明智的选择。