我需要使用递归函数编写N次构成函数f(x)的代码。
我写的是:
let f x = x + 1 (*it can be any function*)
let rec compunere n f x = if n = 0 then
"Nu se mai poate compune"
else compunere (n-1) f (f x);;
这显然是不对的。我知道代码还没有完成,但是我不知道如何继续。我在正确的道路上吗?你能告诉我如何解决这个问题吗?
答案 0 :(得分:3)
您在正确的道路上。根据要求,我将尝试从这些方程式开始:
flush=True
上面说,对compunere 1 f x == f x
一次应用f
与进行x
完全相同。
(f x)
同样,两次应用compunere 2 f x == f (f x)
应该计算f
。如果将f (f x)
替换为对(f x)
的调用,则您将:
compunere
递归的一般模式似乎是:
compunere 2 f x == f (f x) = f (compunere 1 f x)
请注意,compunere n f x == f (compunere (n - 1) f x)
的最一般类型是f
,但是当再次使用类型为a -> b
的值调用f
时,则意味着{{1} }和b
应该是相同的类型,因此a
确实是内胚同构,是类型b
的函数。 N> = 1就是这种情况,但在N = 0的简并情况下,您可能会有不同的行为。
将f
零时间应用于a -> a
可能意味着“返回x”,这意味着f
可以理论上返回类型为{{1}的值}为零,对于任何x
为compunere
函数,a
和f
可能是不同的;您可以使用更多的代码来区分这两种情况,但是在这里,我们可以简单地让类型检查器在所有情况下强制使用a -> b
约束并具有统一的行为。您还可以通过引发异常来使0无效(如负数)(理论上,负应用程序可以是逆函数的正则应用程序,但是当您对f一无所知时,您无法计算出它; f可能是不可逆的)。
您的代码有些不同:
a
您的方法的优势在于,对b
的递归调用直接给出了当前计算的结果:它位于尾部位置,允许编译器执行尾部调用消除。
当您达到N = 0时,本地绑定的a = b
值将提供您想要的结果。在这里,对于N = 0作为输入,唯一自然的解释也是返回compunere 3 f x == (compunere 2 f (f x))
== (compunere 1 f (f (f x)))
== (compunere 0 f (f (f (f x))))
...
。