Sml 为什么可以';我不能围绕addAll函数调用simplify吗?

Sml 为什么可以';我不能围绕addAll函数调用simplify吗?,sml,Sml,我做这个作业是为了做家庭作业,我已经被困在这个问题上3个小时了。我刚刚给教授发了电子邮件,但还没有收到他们的回复,所以我决定也在这里问一下 我们被指派编写各种函数,例如以(14,2)的格式查找分数的gcd,其中14是分子,2是分母 我有gcd、simplify、add和times等函数,但我仍然坚持使用addAll addAll应该获取一个分数列表,这些分数被描述为坐标对,然后将它们相加并简化,然后以一个分数(分子、分母)的形式返回答案 目前,我的addAll函数将它们全部相加并返回正确格式的分

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

我们被指派编写各种函数,例如以(14,2)的格式查找分数的gcd,其中14是分子,2是分母

我有gcd、simplify、add和times等函数,但我仍然坚持使用addAll

addAll应该获取一个分数列表,这些分数被描述为坐标对,然后将它们相加并简化,然后以一个分数(分子、分母)的形式返回答案

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

我目前的代码是:

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;
趣味gcd(a、b)= 如果b=0,则a其他gcd(b,a模式b); (a,b)=如果gcd(a,b)<2,那么(a,b)其他((a分区gcd(a,b)),(b分区gcd(a,b)); 乐趣加(a,b)(c,d)=简化(a*d+c*b,b*d); 娱乐时间(a,b)(c,d)=简化((a*c),(b*d)); fun addAll L=如果L=[]那么[(0,1)]else如果tl L=nil那么L else addAll( [ ((#1(hdl))*(#2(hd(tll)))+(#1(hd(tll)))*(#2(hdl))、(#2(hdl))*(#2(hd(tll))) ] @ (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=[]那么[(1,1)]else如果tl L=nil那么L else timesAll();*) fun lessThan(a,b)(c,d)=如果((实a)/(实b))<((实c)/(实d)),则为真,否则为假;
我终于明白了

    fun addAll L = if L = [] then (0, 1) else if tl L = nil then ((#1 (hd L)) , (#2 (hd 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)))

*)

使用大量选择器编码–如hdtl#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)
这可以简化

但是:您已经实现了加法,因此无需再次执行。
为了添加列表中的所有元素,您可以将其头部添加到其尾部所有元素的相加结果中。
添加一个基本案例,您就有了

fun addAll [] = (0, 1)
  | addAll (x::xs) =  add x (addAll xs);
(您甚至不需要这么多,但您可能还没有学习过
foldl
foldr
。如果已经学习过,请尝试将它们应用于此问题。)


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

请比“我遇到了错误”更具体一些。如果你对模式匹配更加熟悉,你会帮自己一个大忙的。谢谢你,我们甚至还没有学过模式匹配yet@JoshK您已经不知不觉地学会了模式匹配——您的所有其他函数都会这样做,但只在成对的情况下,而不是在列表上。