如何解决如何在SML中仅使用加法函数和迭代函数来制作乘法函数
fun add(x,y) = x + y
fun iterate n f x = if n > 0 then iterate (n-1) f(f x) else x;
仅使用这两个函数,如何编写一个multiply
函数,例如如果键入:
multiply 5 6
返回30。
然后在此基础上,我需要一个名为power
的函数,该函数仅使用iterate
和multiply
将第一个参数提高为第二个参数的幂。一个例子:
power 5 4
它应该返回625。
任何帮助将不胜感激!
解决方法
因此,诀窍是使用iterate
来帮助您递归应用add
。由于iterate
是一个将函数作为参数的列表组合器,因此,如果您以非常简单的方式进行操作,可能会更简单:例如,您可以通过递归地递增或递减来定义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)
现在,由于我们已经有了+
,所以这当然是非常低效的,而且完全没有必要,但是为了演示数字的递归,这是如何使用multiply
和{{ 1}}(仍然假设我们还没有power
)。
此处的一般方法是递归:由于该函数采用两个操作数,因此将一个用作“累加结果”,将另一个用作“计数变量”。因为这是一个简单的问题,所以您仅可以将iterate
和x
用作函数任务的完整环境。在稍大的问题中,您可能会引入更多作为临时/中间结果的参数。
您可以用非常相似的方式写y
:
multiply
此功能解决了任务(尽管仍然没有fun multiply x 0 = 0
| multiply x y = if y > 0
then x + multiply x (y-1)
else ~x + multiply x (y+1)
)。
(此iterate
不是尾部递归的,因为最外面的表达式(multiply
或x + ...
)不是对~x + ...
的调用(因为调用发生在multiply
的操作数之内,这对您来说可能不是问题,但如果是这样,您就很难编写+
,因为当我们使用... then multiply (x + ...) (y - 1)
时在累加结果方面,任何后续递归调用都增加了x
,这意味着我们不能再将x
添加到...本身...,因为x
现在意味着两件事:累加结果,并且每个递归调用都需要添加一次。)
无论如何,要走到最后一步,您必须确定x
与我所做的iterate
和add
的共同点。当您可以找到公分母时,可以将其隔离,然后调用multiply
。我想修复一个空格“ bug”,它可能会使您对iterate
的解释感到困惑:
iterate
添加此空间不会改变函数的行为,但是在阅读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
下表示的是“用三个参数调用then
:iterate
,n-1
和f
;因为f x
的绑定不太紧密而不是函数应用程序,而n-1
是函数应用程序(它是左关联的),我们在它们周围加上括号;对于f x
而言,这不是必需的。”
在f
和add
中,multiply
被用作计数变量,而在y
中,它是iterate
。因此名称和位置已更改,这意味着基于n
的{{1}}必须将multiply
和iterate
放置在正确的位置。至于确定x
的值:将y
添加到其结果中的函数呢?您可以使用lambda f
或部分使用功能x
来表达此功能。
最后,对于(fn z => ...)
,这是几乎相同的问题:
add
由于没有很好的整数解决方案,您必须切换为 real 类型来表示 1 / x ^ n ,也可以翻转条件并在开始递归之前将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"
内部函数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
,除了go
变成了add
和x
变成了result
,并且1
已成为add
,并且没有否定情况(+
)。
因此,这意味着您可以实际使用*
代替if y > 0 ... else ...
,只要您为iterate
找到良好的价值:
-
go
应该是什么? (有点倒计时)。 -
iterate n f x
应该是什么? (执行逐步计算的内容。) -
n
应该是什么? (在逐步计算中应用的内容。)
(...全部用f
表示;在x
函数及其作用域内的参数的上下文中,它们可能被称为其他名称。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。