我正在学习Jason Hickey's Introduction to Objective Caml。
在我学习了第3章之后,我似乎理解let
和fun
是如何工作的。但是,我写自己的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?
答案 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认为它是额外的参数,因此它会产生与您预期不同的类型。放括号将确保您拥有正确数量的参数。当你有很多代码时,调试是一个微妙的问题。所以在类似的情况下使用括号可以节省你这么多时间。 :)