ML;复合函数n次

时间:2016-05-03 15:50:07

标签: sml ml

如何在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));

谢谢

2 个答案:

答案 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
  1. fun repeat f n = if n = 0 then x else composite f repeat(f (n - 1)); 中的x类型错误,因为then x必须返回一个函数。见上文。

  2. 应用repeat f n零次的情况有点棘手。无论结果如何,f都应该给出相同的结果,而不管repeat f 0。或者换句话说,虽然f确实需要返回某些内容,但未应用f

  3. 在递归的情况下,实际上,你只是弄乱了括号。 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))是一个三参数函数,需要compositefrepeat作为参数“和” 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}}。