1

我编写了一个通用例程,它接受多个参数并生成一个无限的斐波那契数列表,如下所示:

datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq) ;
fun fibo (a,b) = Cons(a, fn () => fibo(b,a+b));

val fib = fibo(0 , 1);

但问题是我想使用柯里化技术来生成这个从 0 和 1 开始的无限斐波那契数列表,我对柯里化的概念完全感到困惑。

有人可以通过使用这个例子来启发我关于柯里化的概念吗?如何使用 currying 在 SMLNJ 中生成无限的斐波那契数列表?

4

2 回答 2

3

干得好:

datatype 'a seq = Nil | Cons of 'a * (unit -> 'a seq) ;
fun fibo a b = Cons(a, fn () => fibo b (a + b));

val fib = fibo 0 1;

还有另一个(非常有用的)咖喱函数:

(* take n seq returns the first n items in seq. Raises Subscript if there
   are too few items. *)
fun take 0 _            = []
  | take _ Nil          = raise Subscript
  | take n (Cons (a,f)) = a :: take (n - 1) (f ())

示例(在 mosml 解释器中,因此它可能看起来与 SML/NJ 略有不同):

- take 10 fib;
> val it = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] : int list

只是为了展示一下柯里化的力量:

val firstTen = take 10

- firstTen fib;
> val it = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] : int list

这里发生的事情是,我只给出take一个论点。take有 type int -> 'a seq -> 'a list,所以通过给它int参数,我得到了一些类型的东西'a seq -> 'a list- 即一个返回'a seq你给它作为输入的 10 个项目的函数。

于 2013-11-01T08:46:21.023 回答
0

您的定义有点错误,因为它混合了fibo.

如果我理解正确,那么在编码级别上没有什么可以启发您的。curried 和 uncurried 定义之间存在微小的句法差异。

- fun plus_uncurried (a, b) = a + b;
val plus_uncurried = fn : int * int -> int
- plus_uncurried (3,5);
val it = 8 : int
-  fun plus_curried a b = a + b;
val plus_curried = fn : int -> int -> int
- plus_curried 3 5;
val it = 8 : int
- val incr = plus_curried 1;
val incr = fn : int -> int
- incr 4;
val it = 5 : int

在概念层面上,柯里化函数似乎有点棘手,至少一开始是这样。我个人只是将柯里化函数视为返回需要更多参数的函数的函数。当你最终给出最后一个论点时,你就会得到答案。

(我不确定你为什么用 OCaml 标记这个问题,但在 OCaml 中,柯里化是函数的惯用形式。所以你马上就习惯了。)

您可能正在寻找比 type 函数更复杂的东西int -> int -> int seq。如果是这样,您需要更仔细地描述您要查找的内容。只需指定您要查找的内容的类型可能会有很大帮助。

更新

fibo除了你有一个递归调用之外,没有什么比上面的例子更复杂了。如果您只是以与更改为fibo相同的方式更改 的第一部分,您将处理定义部分。要处理调用部分,请以将调用更改为调用相同的方式更改递归调用。plus_uncurriedplus_curriedplus_uncurriedplus_curried

于 2013-10-31T19:07:55.677 回答