将 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
  | ...

特别是:您可能需要重新考虑对和列表可能评估的有意义的标量值,以及是否应该将对和列表限制在语法树的某些部分.

通常:每次你的模式匹配更深一层,匹配案例的数量就会乘以构造函数的数量。一级或二级匹配通常就足够了。如果没有,编写执行更深匹配的辅助函数几乎总是明智的选择。