我编写了一个通用例程,它接受多个参数并生成一个无限的斐波纳契数列表,如下所示:
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);
但问题是我想用currying技术从0和1开始生成这个无限的斐波纳契数列表,我对currying的概念感到非常困惑。
通过使用这个例子可以让我了解一下currying的概念吗?如何使用currying在SMLNJ中生成无限的斐波纳契数列表?
答案 0 :(得分: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
的类型为int -> 'a seq -> 'a list
,所以通过给它int
参数,我得到类型为'a seq -> 'a list
的东西 - 即一个返回'a seq
的10个项的函数你把它作为输入。
答案 1 :(得分:0)
你的定义有点不对,因为它混合了fibo
的curry和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
在概念层面,咖喱功能似乎有点棘手,至少在开始时是这样。我个人只是想到一个curried函数作为一个返回一个需要更多参数的函数。当你最后给出最后一个论点时,你会得到答案。
(我不确定你为什么用OCaml标记这个问题,但在OCaml currying中是函数的惯用形式。所以你马上就习惯了。)
您可能正在寻找比int -> int -> int seq
类型的函数更复杂的东西。如果是这样,你需要更仔细地描述一下你在寻找什么。只要指明你要找的东西的类型可能会有很大的帮助。
<强>更新强>
fibo
中没有比上面的例子更复杂的了,除了你有一个递归调用。如果您只是更改fibo
的第一部分,就像plus_uncurried
更改为plus_curried
一样,您将处理定义部分。要处理呼叫部分,请更改递归呼叫,方法与将plus_uncurried
的呼叫更改为plus_curried
的呼叫相同。