我有一个无限列表的任务。
我必须为无限列表编写一个zipWith / 3 - 已完成
我必须使用这个zipWith / 3来创建一个无限的fibonacci数字列表,其中包含fib / 0 - 问题
我必须从fib() - 完成
中获取前N个元素的fibs(N)这是我到目前为止所做的:
-module(zipWith).
-export([take/2, zipWith/3, fib/0]).
take(0, _) -> [];
take(N, [H|LazyT]) -> [H | take(N-1, LazyT())].
zipWith(F, [H1|L1], [H2|L2]) -> [F(H1, H2) | fun() -> zipWith(F, L1(), L2()) end].
fib() -> ...
fib(L) -> zipWith(fun(X,Y) -> X + Y end, L(), tl(L())).
fibs(N) -> take(N, fib()).
我知道fib / 1应该是这样的(我很确定 - 如果我弄错了,请纠正我)。列表本身和列表没有头。因此,如果[0,1,...] zipWith(add,[0,1,...],[1,...])导致添加最后两个数字。但无论我尝试作为这个fib()的开始 - > ...导致错误。 我想以某种方式表达它: fib() - > fib([[0,1] ++ fun() - > ... end] ...)
我不知何故想用[0,1,fun()...]启动fib / 1,但是不知道如何让列表开始。
提前感谢您的建议
答案 0 :(得分:2)
我不明白你将如何在这里使用zipwith
。但是,我提出了以下解决方案:
map(_, []) -> [];
map(F, [H | T]) -> [F(H) | fun() -> map(F, T()) end].
fib1(X, Y) -> [{X, Y} | fun() -> fib1(Y, X+Y) end].
fib() -> map(fun({_X, Y}) -> Y end, fib1(1,1)).
想法是构建一些元素,然后传递下一个数字的上下文。
实际上,我并不认为这种方法可以实现真正的懒惰,因为每次进入列表时都必须重新评估所有值。
如果你想通过zipWith
实现这一点,你可以解决这个问题,即序列的每个下一个元素都是前一个元素和当前元素的总和。
因此,您可以获取元素列表,以及一个元素列表,并将每个下一个元素组合为这些列表中elemet的总和。
你需要一些先进的elemetns来引导。您只需应用前两个元素的知识
正如你所看到的,在计算第3个元素的时候你必须首先知道2,在计算第4个元素时,你必须知道第2个和第3个,但你已经计算了第3个。
%% this eveluates the lazy list and just returns normal one
e(L) when is_list(L) -> L;
e(LazyL) when is_function(LazyL, 0) -> LazyL().
take(0, _) -> [];
take(N, [H|LazyT]) -> [H | take(N-1, e(LazyT))].
drop(0, T) -> e(T);
drop(N, [_|LazyT]) -> drop(N-1, e(LazyT)).
zipWith(F, [H1|L1], [H2|L2]) -> [F(H1, H2) | fun() -> zipWith(F, e(L1), e(L2)) end].
fib() -> [1, 1 | fun() -> zipWith(fun(X,Y) -> X + Y end, fib(), drop(1, fib())) end ].
fibs(N) -> take(N, fib()).