如何在ML中复合函数f n次?
复合两次; f(fx) 复合三次; f(f(fx))) 复合n次; F(F(F(˚F.....(FX)))))))
我试过了;
fun composite f g =
let h x = f(g x)
in h end;
fun repeat f n =
if n = 0 then x
else composite f repeat(f (n - 1));
谢谢
答案 0 :(得分:3)
编写递归函数时,将问题分为一般,递归情况和不需要递归的基本情况。例如,组合一个函数 n 次听起来像基本情况可能是 n = 0 或 n = 1 时(或者可以工作;我会回到那个。)
我鼓励模式匹配,但是当递归整数时, if-then-else 看起来一样简单。在任何情况下,所有示例都以两种样式编写。一个简单的骨架可能是:
fun repeat f n =
if n = 0
then ?
else ?
fun repeat f 0 = ?
| repeat f 1 = ?
| repeat f n = ?
我想这里的一些困难是repeat
必须返回一个函数。从语法上讲,您可以通过各种方式实现这一目标。与约翰建议的一样,您可以通过repeat
扩展x
来编写它:
fun repeat f n x =
if n = 1
then f x
else ...
fun repeat f 1 x = f x
| repeat f n x = ...
自然但有点奇怪的解释是“ repeat
是一个带有三个参数的函数;函数f
,它必须应用的次数{{1 }和n
的参数f
(?!)“。
或者,也可以像
一样编写它x
可能被解释为“ fun repeat f n =
if n = 1
then (fn x => f x)
else ...
fun repeat f 1 = (fn x => f x)
| repeat f n = ...
是一个带有两个参数的函数;函数repeat
及其必须应用的次数f
,并返回一个将n
应用于其参数f
次的函数。“
这些定义实际上是等同的。你会看到通过将描述翻译成类型:
n
val repeat : ('a -> 'a) -> int -> 'a -> 'a
第一个类型签名中隐含了最后一个括号。
有时将多个 curried 参数的函数视为“具有多个参数的函数”会有所帮助,有时将它们视为“返回带有其他参数的函数的函数”会有所帮助。 val repeat : ('a -> 'a) -> int -> ('a -> 'a)
似乎是这个的混合物; repeat
最好被认为是“第二个参数”,但n
最好被认为是“我们返回的函数所带来的论证”。
使用此首选项以及模式匹配的首选项,我建议的基础是:
x
因为fun repeat f 0 = ...
| repeat f 1 = f
| repeat f n = ...
和(fn x => f x)
实际上是同一个功能。
你写道:
f
fun repeat f n =
if n = 0 then x
else composite f repeat(f (n - 1));
中的x
类型错误,因为then x
必须返回一个函数。见上文。
应用repeat f n
零次的情况有点棘手。无论结果如何,f
都应该给出相同的结果,而不管repeat f 0
。或者换句话说,虽然f
确实需要返回某些内容,但未应用f
。
在递归的情况下,实际上,你只是弄乱了括号。 John透露了repeat f 0
运算符,它是标准ML的内置版o
,我也更喜欢它:
composite
您需要了解有关标准ML中括号的内容:您主要将它们添加到组内容中。当你写composite f (repeat f (n-1))
f o repeat f (n-1)
时,你所说的是:“ composite f repeat (f (n-1))
是一个三参数函数,需要composite
,f
和repeat
作为参数“和” f (n-1)
是一个以整数作为参数的函数。“
当您真正想说的是“ f
需要composite
以及将f
与自身f
合成的结果 - 1次,并撰写那些。“当你来自希望函数调用看起来像 n
的语言时,这是一个经典的错误,而且人们认为这会转化为 foo(arg1, arg, arg3)
实际上你想要 foo(arg1 arg arg3)
。在标准ML中,此括号强制 foo arg1 arg2 arg3
被视为函数并将其应用于 arg1
和 arg2
,并将 arg3
应用于该结果。糟糕!
答案 1 :(得分:2)
你的想法接近正确。你可以使用currying使它们工作:
@using (Html.BeginForm())
{
<div class="panel panel-default">
<div class="panel-body">
<p>
<strong>Campus</strong>: @Html.DropDownList("campus",
new SelectList(ViewBag.CampusList)) ||
<strong>FY</strong>: @Html.DropDownList("fy",
new SelectList(ViewBag.FyList))
</p>
<div><input type="submit" value="Search" /></div>
</div>
</div>
}
SML将其类型推断为:
fun composite f g x = f(g(x));
这完全适合作曲。函数应用程序是左关联的,所以
val composite = fn : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
解析为
composite f g x
因此,函数定义读作给出了将函数(composite f g) x
应用于参数(composite f g)
的含义。当然,其含义是返回值x
。
你可以测试一下:
f(g(x))
然后,例如fun square x = x*x
fun increment x = x + 1
val h = composite increment square
按预期评估为h 5
。
类似的调整适用于您的第二个定义。它可以开始:
26
因为这看起来像是家庭作业,我会把细节留给你,但你目前的尝试是非常接近正确的解决方案。
说完这一切之后,你应该知道组合是SML中的内置运算符,用小写fun repeat f n x =
表示,o
可以在你的第二个定义中用来代替{ {1}}。