首页 > 解决方案 > 为什么我不能围绕我的 addAll 函数调用简化?

问题描述

我正在做这个家庭作业,我已经在这个问题上停留了大约 3 个小时。我刚刚给教授发了电子邮件,但还没有收到他们的回复,所以我决定也在这里问。

我们被分配编写各种函数,例如找到格式为 (14, 2) 的分数的 gcd,其中 14 是分子,2 是分母。

我已经完成了 gcd、simplified、add 和 time 的功能,但我卡在 addAll 上。

addAll 应该获取一个描述为坐标对的分数列表,并将它们全部加起来并简化它,并将答案作为一个这样格式化的分数(分子,分母)返回。

目前,我的 addAll 函数将它们全部加起来并返回格式正确的分数,但它并没有简化它。我已经编写了简化函数,但是每当我尝试围绕我的 addAll 递归调用调用简化时,我都会收到错误消息。

我目前的代码是这样的:

fun addAll L = if L = [] then [(0, 1)] else if tl L = nil then L else addAll(    

[
( ((#1 (hd L)) * (#2 (hd (tl L)))) + (#1 (hd (tl L))) * (#2 (hd L)), (#2 (hd L))*(#2 (hd (tl L))) )
]

@

(tl (tl L))

);

(*

a = (#1 (hd L))
b = (#2 (hd L))
c = (#1 (hd (tl L)))
d = (#2 (hd (tl L)))

*)

我试图通过这样做来解决问题:

fun addAll L = if L = [] then [(0, 1)] else if tl L = nil then L else simplify(addAll(    

[
( ((#1 (hd L)) * (#2 (hd (tl L)))) + (#1 (hd (tl L))) * (#2 (hd L)), (#2 (hd L))*(#2 (hd (tl L))) )
]

@

(tl (tl L))

));

(*

a = (#1 (hd L))
b = (#2 (hd L))
c = (#1 (hd (tl L)))
d = (#2 (hd (tl L)))

*)

但我遇到了错误。

任何帮助,将不胜感激。

谢谢。

另外,如果有帮助,我将附上我在 sml 中运行的整个代码......

这是我所有的作业代码:

fun gcd (a, b) =
if b = 0 then a else gcd(b, a mod b);

fun simplify (a, b) = if gcd(a, b) < 2 then (a, b) else ((a div gcd(a, b)), (b div gcd(a, b)));

fun add (a,b) (c,d) = simplify((a*d + c*b), b*d);

fun times (a,b) (c,d) = simplify( (a*c), (b*d) );

fun addAll L = if L = [] then [(0, 1)] else if tl L = nil then L else addAll(    

[
( ((#1 (hd L)) * (#2 (hd (tl L)))) + (#1 (hd (tl L))) * (#2 (hd L)), (#2 (hd L))*(#2 (hd (tl L))) )
]

@

(tl (tl L))

);

(*

a = (#1 (hd L))
b = (#2 (hd L))
c = (#1 (hd (tl L)))
d = (#2 (hd (tl L)))

*)



(*fun timesAll L = if L = [] then [(1, 1)] else if tl L = nil then L else timesAll();*)



fun lessThan (a, b) (c, d) = if ((real a) / (real b)) < ((real c) / (real d)) then true else false;

标签: sml

解决方案


带有很多选择器的代码——比如hd, tl, #1, ...——很难阅读。
这是您使用模式匹配的功能,这在视觉上要容易得多:

fun addAll [] = [(0,1)]
  | addAll [x] = [x]
  | addAll ((a0, b0)::(a1, b1)::xs) = addAll ((a0 * b1 + a1 * b0, b0 * b1) :: xs)

(我也[x] @ xs用. 替换了结构x :: xs。)

问题是这个函数应该产生一对,而不是一对列表:

fun addAll [] = (0,1)
  | addAll [x] = x
  | addAll ((a0, b0)::(a1, b1)::xs) = addAll ((a0 * b1 + a1 * b0, b0 * b1) :: xs)

这可以simplify编辑。

但是:你已经实现了加法,所以你不必再做一次。
为了添加列表中的所有元素,您可以将其头部添加到添加其尾部的所有元素的结果中。
添加一个基本案例,你有

fun addAll [] = (0, 1)
  | addAll (x::xs) =  add x (addAll xs);

(你甚至不需要这么多,但你可能还没有学习过foldlfoldr如果你有,试着把它们应用到这个问题上。)

您可以timesAll以相同的方式简化您的功能。


推荐阅读