问题
I have coded up a general purpose routine that takes multiple arguments and generates an infinite list of fibonacci numbers which is as follows:
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);
But the problem is I want to use currying technique to generate this infinite list of fibonacci numbers starting from 0 and 1, I am totally perplexed about the concept of currying.
Can some enlighten me about the concept of currying by using this example? How do I use currying to generate an infinite list of fibonacci numbers in SMLNJ?
回答1:
Here you go:
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;
And another (very useful) curried function:
(* 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 ())
Example (in the mosml interpreter, so it might look slightly different from SML/NJ):
- take 10 fib;
> val it = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] : int list
And just to show off a little of the power of currying:
val firstTen = take 10
- firstTen fib;
> val it = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] : int list
What happens here, is that I only give take
one argument. take
has type int -> 'a seq -> 'a list
, so by giving it the int
argument, I get something of type 'a seq -> 'a list
- namely, a function that returns 10 items of the 'a seq
you give it as input.
回答2:
Your definition is a little wrong as it mixes curried and uncurried forms of fibo
.
If I understand correctly, there's not much to enlighten you about at the level of coding. There's a tiny syntactic difference between the curried and uncurried definitions.
- 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
At the conceptual level, curried functions seem a little trickier, at least at first. I personally just think of a curried function as one that returns a function that wants more arguments. When you finally give the last argument you get your answer.
(I'm not sure why you tagged this question with OCaml, but in OCaml currying is the idiomatic form for functions. So you get used to it right away.)
It may be you're looking for something more complicated than a function of type int -> int -> int seq
. If so, you'll need to describe a little more carefully what you're looking for. Just specifying the type of what you're looking for would probably help a lot.
Update
There's nothing more complicated in fibo
than in the examples above, other than that you have a recursive call. If you just change the first part of fibo
in the same way that plus_uncurried
changes into plus_curried
, you will have handled the definition part. To handle the calling part, change your recursive call in the same way that calls to plus_uncurried
are changed into calls to plus_curried
.
来源:https://stackoverflow.com/questions/19713850/how-to-generate-an-infinite-list-of-fibonacci-numbers-using-curried-function-in