编写OCaml函数的正确和顺畅的方法是什么?

时间:2012-12-04 15:05:06

标签: functional-programming ocaml

我正在学习Jason Hickey's Introduction to Objective Caml

在我学习了第3章之后,我似乎理解letfun是如何工作的。但是,我写自己的fun时遇到了麻烦。


以下是我遇到的一个示例问题

Write a function sum that, given two integer bounds n and m and a function f, computes a summation (no for loop allowed). i.e., sum n m f = f(n) + f(n+1) + ... + f(m)


那么,我该如何开始考虑产生这个函数和?

在Java或普通编程语言中,很容易。

因为这里不允许使用循环,所以我想我应该以{{1​​}}的方式进行循环?

这样的事情:

let rec

我需要let rec sum n m f = fun i -> ....作为游标吗?

无论如何,我无法继续思考。

有人能指出让我产生OCaml乐趣的道路吗?


这是我的最终解决方案:

i

但当然,这是错误的。错误为let rec sum n m f = if n <= m then (f n)+(sum n+1 m f) else 0;;

为什么呢?什么是'a?

3 个答案:

答案 0 :(得分:6)

您犯了一个经典的语法错误:sum n+1 m f被解析为(sum n) + (1 n f)而不是您期望的。在OCaml中,函数应用程序(空间)具有比中缀运算符更强的优先级。

类型错误来自于sum n(您在求和中使用)不是整数的事实。它需要一个参数(m)和一个返回整数的函数。在类型推断过程的这一点上(当错误发生时),OCaml将其表示为'a -> ('a -> int) -> 'b:将一些未知的东西a,一个函数从a转换为int,并返回一些东西b

答案 1 :(得分:6)

我希望这会帮助你思考递归而不是循环(让我们暂时忽略尾递归)。

所以你需要计算f(n) + f(n+1) + ... f(m)。它可能会帮助您以归纳的方式来思考这个问题。也就是说,假设您知道如何计算f(n+1) + ... + f(m),那么您需要做些什么来计算原始结果?好吧,你只需将f(n)添加到后者,对吗?这正是你的代码所说的:

let rec sum n m f =
  if n = m then
    f m
  else
    f n + sum (n + 1) m f;; (* here's the inductive step *)

您可以看到我如何将f(n)添加到f(n+1) + .... + f(m)的结果中。因此,以归纳的方式思考,将问题分解成小块,并思考如何将这些小块的结果放在一起。

希望我没有让事情变得更加混乱。

答案 2 :(得分:1)

'a就像Java中的泛型类型。例如: let test a = 1 它的类型是'a -> int 无论你的论证类型如何,这个函数都会返回1。

错误是您需要在此处添加括号 (sum (n+1) m f)

Ocaml认为它是额外的参数,因此它会产生与您预期不同的类型。放括号将确保您拥有正确数量的参数。当你有很多代码时,调试是一个微妙的问题。所以在类似的情况下使用括号可以节省你这么多时间。 :)