Sml 毫升;复合函数n次

Sml 毫升;复合函数n次,sml,ml,Sml,Ml,如何在ML中合成函数fn次 复合两次;f(外汇) 复合三次;f(f(fx))) 复合n次;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)); 谢谢你你的想法几乎是正确的。你可以用咖喱来使它

如何在ML中合成函数fn次

复合两次;f(外汇) 复合三次;f(f(fx))) 复合n次;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));

谢谢你

你的想法几乎是正确的。你可以用咖喱来使它们起作用:

fun composite f g x = f(g(x));
SML推断其类型为:

val composite = fn : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
这对构图来说是完全正确的。函数应用程序是左关联的,因此

composite f g x 
解析为

(composite f g) x
因此,函数定义的含义是将函数
(复合f g)
应用于参数
x
。当然,其含义是返回值
f(g(x))

您可以测试它:

fun square x = x*x
fun increment x = x + 1
val h = composite increment square
然后,例如,
h5
按预期计算为
26

类似的调整适用于第二个定义。它可以开始:

fun repeat f n x =
因为这看起来像是家庭作业,我将把细节留给你,但是你目前的尝试非常接近于正确的解决方案


说到这里,您应该知道composition是SML中的一个内置操作符,用小写的
o
表示,并且
(op o)
可以在您的第二个定义中代替
composite

,当您编写递归函数时,将问题划分为一般的递归情况,以及不需要递归的基本情况。例如,将一个函数自身组合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
必须返回一个函数。从语法上讲,你可以通过各种方式来实现。正如John所建议的,您可以通过使用
x
扩展
repeat
来编写它:

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
,必须应用的次数
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重复:('a->'a)->int->'a->'a
  • val重复:('a->'a)->int->('a->'a)
最后一个括号隐含在第一个类型签名中

有时,将具有多个curry参数的函数视为“具有多个参数的函数”会有所帮助,而有时,将它们视为“返回具有其他参数的函数”会有所帮助。而
repeat
似乎是这两者的混合体
n
最好被认为是“第二个参数”,而
x
最好被认为是“我们返回的函数所使用的参数”

有了这个偏好和模式匹配的偏好,我建议的基础是:

fun repeat f 0 = ...
  | repeat f 1 = f
  | repeat f n = ...
因为
(fnx=>fx)
f
实际上是一个相同的函数

关于基情形和递归情形 你写道:

  • then x
    中的
    x
    类型错误,因为
    repeat f n
    必须返回一个函数。见上文

  • 应用
    f
    0次时的情况有点棘手。无论结果是什么,
    repeat f0
    应该给出相同的结果,而不管
    f
    。或者换句话说,
    f
    不被应用,尽管
    repeat f0
    确实需要返回一些东西

  • 在递归的情况下,实际上,你只是把括号搞乱了。John透露了
    o
    操作符,这是Standard ML内置的
    composite
    版本,我也更喜欢它:

    composite f (repeat f (n-1))
    f o repeat f (n-1)
    
    关于标准ML中的括号,您需要了解的是:您主要将它们添加到分组中。当您编写
    composite f repeat(f(n-1))
    时,您要说的是:“
    composite
    是一个三参数函数,它接受
    f
    repeat
    f(n-1)
    作为参数,
    f
    是一个接受整数作为参数的函数。”

    当你真正想说的是“
    composite
    接受
    f
    和用自身
    n
    组合
    f
    的结果–1次,然后组合这些。”当你来自那些期望函数调用看起来像
    foo(arg1,arg,arg3)的语言时,这是一个典型的错误
    有人认为这会转化为
    foo(arg1 arg arg3)
    而实际上您需要
    foo arg1 arg2 arg3
    。在标准ML中,此括号强制将
    arg1
    视为一个函数,并将其应用于
    arg2
    arg3
    ,并将
    foo
    应用于该函数的结果。哎呀


  • 我喜欢你的一些答案有多详细。他们提供了很多信息供学生思考。非常感谢。我对n=0分支有一个问题,但现在很清楚我做错了什么。谢谢。我现在明白了括号的用法。
    composite f (repeat f (n-1))
    f o repeat f (n-1)