【问题标题】:OCaml recursive function to apply a function n timesOCaml 递归函数应用函数 n 次
【发布时间】:2013-02-23 11:44:36
【问题描述】:

我想在 OCaml 中创建一个 int -> ('a -> 'a) -> 'a -> 'a 类型的函数,它接受一个 int n (非否定)和一个函数 f 'a -> 'a 和类型为 'a 的参数 a。 f 应该被调用 n 次。

我尝试了 3 种不同的方法,但只能得到 int -> ('a -> 'b) -> 'a -> 'b,这是我尝试过的一些方法。

let rec f n g a = 
g a;
f (n-1) g a;;

给了

val f : int -> ('a -> 'b) -> 'a -> 'c = <fun>

我试过了

    let rec f n g a =
  if n > 0 then f (n-1) g a
  else g a
  ;;

这给了我

val f : int -> ('a -> 'b) -> 'a -> 'b = <fun>

第二个更接近,但我不知道如何获得 int -> ('a -> 'a) -> 'a -> 'a

【问题讨论】:

    标签: function functional-programming ocaml


    【解决方案1】:

    我不太确定您要做什么。我猜是下面的函数:

    let rec foldi i f acc =
        if i <= 0 then acc else foldi (pred i) f (f acc)
    

    它递归地将i 乘以函数f 应用于值acc,然后应用于其结果。 foldi 可能不是它的最佳名称。

    【讨论】:

    • 您的代码中的 pred i 到底是什么?它似乎减一?
    • predsucc 的对偶,它返回其(整数)参数的前身,即。该值减一。
    • 是的,你的猜测是正确的。它在Pervasives 模块中定义。
    • 为这种琐碎的操作定义函数可能看起来很奇怪,但由于它们经常出现,它实际上非常方便。
    • 哦,我意识到,我对 java 比较熟悉,我喜欢我的 i++;我——等等。
    【解决方案2】:

    一旦你正确编写了函数,类型就会变直。您第二次尝试的问题是它为f5 0 ... 提供了错误的答案。在我看来,您根本不想在这种情况下应用该功能。

    也许下面的例子会说明我的意思:

    # let add1 x = x + 1;;
    val add1 : int -> int = <fun>
    # f5 2 add1 3;;
    - : int = 5
    # f5 1 add1 3;;
    - : int = 4
    # f5 0 add1 3;;
    - : int = 3
    # 
    

    在我看来,这些是你应该得到的答案。

    【讨论】:

    • 用 >= 替换 > 似乎没有帮助。那是大于/等于的正确运算符还是我在其他地方的错误?
    • 您的错误在别处。你需要有一个对争论没有任何作用的案例。您的代码中没有这样的情况。 (如果你想偷看,你可以在 didierc 的答案中看到解决方案。)
    • 再次感谢您的帮助,我承认我确实偷看了。
    【解决方案3】:
    let rec f n g a =
    if n > 0 then f (n-1) g a
    else g a
    ;;
    

    差不多就这些了,但是你要多了解你的问题,也许只是f^n的定义。您可以通过以下方式定义 f^n:对于所有 x,f^n(x) = f^(n-1)(f(x)) 和 f^0(x) = x

    在您的代码中,您有 f (n-1) g a,即 f^(n-1)(x) 与我的符号。你永远不会应用 f,只是在最后。

    解决办法是: f (n-1) g (g a) !!!

    你必须每次都申请 g。

    【讨论】:

      【解决方案4】:

      几分钟前我碰巧写了一个工作版本:

      let rec applyn n func arg =
      if n <= 0 then
          arg
      else
          applyn (n-1) func (func arg)
      

      请注意,每次进行递归调用时都会发生函数应用程序。在您的代码中, g 仅被调用一次; OCaml 不能推断它是 'a -> 'a,所以给出 'a -> 'b。

      【讨论】:

        猜你喜欢
        • 2013-05-20
        • 2012-10-17
        • 1970-01-01
        • 2018-03-18
        • 2018-04-02
        • 2012-04-30
        • 1970-01-01
        • 2015-12-08
        • 2013-03-30
        相关资源
        最近更新 更多