如何在SML中使用加法函数和迭代函数生成乘法函数
我在SML中有两个函数,如何在SML中使用加法函数和迭代函数生成乘法函数,sml,smlnj,Sml,Smlnj,我在SML中有两个函数,add和iterate fun add(x,y)=x+y fun iterate n f x=如果n>0,则迭代(n-1)f(f x)else x; 仅使用这两个函数,如何编写乘法函数,例如,如果键入: multiply 5 6 返回30 在此基础上,我需要一个名为power的函数,它只使用iterate和multiply将第一个参数提升为第二个参数的幂。例如: power 5 4 它应该返回625 任何帮助都将不胜感激 所以诀窍是使用迭代来帮助您递归地应用添加。由
add
和iterate
fun add(x,y)=x+y
fun iterate n f x=如果n>0,则迭代(n-1)f(f x)else x;
仅使用这两个函数,如何编写乘法
函数,例如,如果键入:
multiply 5 6
返回30
在此基础上,我需要一个名为power
的函数,它只使用iterate
和multiply
将第一个参数提升为第二个参数的幂。例如:
power 5 4
它应该返回625
任何帮助都将不胜感激 所以诀窍是使用
迭代
来帮助您递归地应用添加
。由于iterate
是一个以函数为参数的列表组合器,如果您以非常简单的方式进行操作,可能会更简单:例如,您可以通过递归递增/递减1来定义add
:
(* Written using if-then-else *)
fun add x y =
if y = 0 then x else
if y > 0 then add (x+1) (y-1) else add (x-1) (y+1)
(* Written using mixture of pattern-matching and if-then-else *)
fun add x 0 = x
| add x y = if y > 0
then add (x+1) (y-1)
else add (x-1) (y+1)
现在,这当然是非常低效和完全没有必要的,因为我们已经有了+
,但是为了演示数字的递归,这是一个如何使用乘法和幂
的例子(仍然假设我们还没有迭代
)
这里的一般方法是递归:因为函数需要两个操作数,所以使用一个作为“累加结果”,另一个作为“计数变量”。因为这是一个简单的问题,所以您可以使用x
和y
作为函数任务的完整环境。在稍微大一点的问题中,您可能会引入更多作为临时/中间结果的参数
您可以用非常类似的方式编写乘法
:
fun multiply x 0 = 0
| multiply x y = if y > 0
then x + multiply x (y-1)
else ~x + multiply x (y+1)
此函数用于解决任务(尽管仍然没有迭代)
(这个乘法
不是尾部递归的,因为最外层的表达式(x+…
或~x+…
)不是对乘法
的调用(因为调用发生在+
的操作数内部)。这对您来说可能不是问题,但如果是,您就无法轻松编写…然后乘法(x+…)(y-1)
,因为当我们使用x
来累加结果时,任何后续递归调用都会增加x
,这意味着我们不能再将x
添加到…本身…因为x
现在意味着两件事:累加结果和每次递归调用需要添加一次的内容。)
无论如何,要完成最后一步,您必须确定iterate
与我制作的add
和multiply
有什么共同之处。当您能够发现公共分母时,您可以将其隔离并调用iterate
。我想修复一个可能会混淆您对迭代的解释的空白“bug”:
fun iterate n f x = if n > 0
then iterate (n-1) f (f x)
else x; (* ^- this space! *)
添加此空格不会改变函数的行为,但是当读取f(f x)
时,人们会倾向于相信它说“将f
应用到f x
”,这是错误的解释。在下,这个函数实际上说的是“调用迭代,有三个参数:n-1
,f
和fx
;因为n-1
绑定比函数应用程序更紧密,fx
是函数应用程序(左关联),我们在其周围添加括号;这对于f
不是必需的
在add
和multiply
中,y
被用作计数变量,而在iterate
中则是n
。因此名称和位置发生了变化,这意味着基于iterate
的multiply
必须将x
和y
放在正确的位置。至于确定f
的值:将x
添加到其结果中的函数如何?您可以使用lambda、(fn z=>…)
来表示此函数,也可以使用函数的部分应用程序add
最后,使用power
时,问题大致相同:
fun power x 0 = 1
| power x n = if n > 0
then x * power x (n-1)
else raise Fail "Cannot express 1/x^n as integer"
由于整数没有一个好的解决方案,您必须切换到实数类型以表示1/x^n,也可以在开始递归之前翻转条件并从图片中获取n<0
的情况:
fun power x n =
if n < 0 then raise Fail "Cannot express 1/x^n as integer"
else let fun go result 0 = result
| go result i = go (result * x) (i-1)
in go 1 n
end
fun power x n=
如果n<0,则raise Fail“无法将1/x^n表示为整数”
否则让乐趣消失结果0=结果
|通过结果i=通过(结果*x)(i-1)
围棋1N
结束
内部函数go
看起来非常像上面的add
,除了x
变成了result
,1
变成了add
,+
变成了*
,没有否定的情况(如果y>0…否则…
)
因此,这意味着您实际上可以使用iterate
而不是go
,只要您为iterate n f x
找到好的值:
n
应该是什么?(倒计时。)
f
应该是什么?(执行逐步计算的东西。)
x
应该是什么?(逐步计算中应用的内容。)
(…所有的迭代
;在power
函数及其作用域中的参数的上下文中,它们可能被称为其他名称。)非常感谢!我是SML的新员工,在语法上我是个铁杆。