【问题标题】:How do we write Recursive function in SML?我们如何在 SML 中编写递归函数?
【发布时间】:2020-12-10 06:41:23
【问题描述】:

这是我正在实现的递归函数的 python 代码。

def f(x):
  return x+1
def iter(n, f,x):
  if n == 0:
    return x
  return iter(n-1, f, f(x))

调用迭代器

iter(7, f, 9)

如何用 SML 编写?

fun iter 0 f x = x
  |iter n f x = iter(n-1, f, f(x));    

【问题讨论】:

    标签: sml smlnj


    【解决方案1】:

    OP 代码将 curried 函数表示法与元组表示法混合在一起。 OP 定义了一个 curried 函数,然后在递归调用中将一个元组传递给它。有两个明显的解决方案:决定是否需要柯里化表示法或元组表示法,并始终如一地使用它。

    使用元组表示法iter 接受一个包含参数的元组,也就是说,这里iter 实际上只接受一个参数,它是一种包含参数的数据类型。也就是说,元组iter 的类型为:fn : int * ('a -> 'a) * 'a -> 'a

    fun iter (0, _, x) = x
      | iter (n, f, x) = iter(n-1, f, f x);
    

    上面的表达方式可能有点不同,例如iter((n-1), f, (f x)),或iter((n-1), f, f(x))

    使用柯里化符号 iter 接受单个 int 参数并返回一个接受函数参数的函数,返回一个接受与传递函数匹配的参数的函数。也就是说,咖喱 iter 的类型为 fn : int -> ('a -> 'a) -> 'a -> 'a

    fun iter 0 _ x = x
      | iter n f x = iter (n-1) f (f x);
    

    元组版本和柯里化版本是两种截然不同的情况。对于元组版本,如果您传递的“参数”少于三个,则会出现类型错误,例如:

    - iter(2, double);
    stdIn:1.2-1.17 Error: operator and operand do not agree [tycon mismatch]
      operator domain: int * ('Z -> 'Z) * 'Z
      operand:         'Y[INT] * (int -> int)
      in expression:
        iter (2,double)
    

    问题在于元组版本需要一个包含三个字段的元组参数。传递少于三个字段的元组违反了这种预期。

    但是对于 curried 版本,如果您传递的参数少于三个,则您有一个偏函数应用程序:

    - val doubleTwice = iter 2 double;
    val doubleTwice = fn : int -> int
    - doubleTwice 3;
    val it = 12 : int
    - doubleTwice 5;
    val it = 20 : int
    

    在这里,只将两个参数传递给 curried iter,其中一个是一个将 int 加倍的 double 函数,返回一个将输入值加倍的函数。 Curried 函数可能非常有用,您需要了解这两种样式之间的区别。

    【讨论】:

      【解决方案2】:

      语法是:

      fun iter 0 f x = x
        | iter n f x = iter (n-1) f (f x);
      

      注意:您可以在第 1 行将f 替换为_,因为f 不会出现在结果表达式中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-29
        • 1970-01-01
        • 1970-01-01
        • 2015-06-19
        • 1970-01-01
        • 1970-01-01
        • 2014-08-15
        • 1970-01-01
        相关资源
        最近更新 更多