根据前面的元素计算列表的下一个元素
Compute next element of list based on previous elements
我想定义一个无限列表,其中每个元素都是前面所有元素的函数。
因此,列表的第 n+1
个元素将是 f [x1, x2, ..., xn]
。
这看起来很简单,但我似乎无法理解如何去做。有人可以帮忙吗?
您可以使用 unfoldr
:
import Data.List
gen :: ([a] -> a) -> a -> [a]
gen f init = unfoldr (\l -> let n = f (reverse l) in (Just (n, n:l))) [init]
请注意,每次都必须反转输入列表。您可以使用 Data.Sequence
代替:
import Data.Sequence
genSeq :: (Seq a -> a) -> a -> Seq a
genSeq f init = unfoldr (\s -> let n = f s in (Just (n, s |> n))) (singleton init)
作为另一个答案的替代方案,希望它更具可读性但不那么简洁:
-- "heads f" will generate all of the the prefixes of the inflist
heads f = map ( (flip take) (inflist f) ) [1..]
-- inflist will generate the infinite list
inflist f = ( f [] ) : map f (heads f)
-- test function
sum1 s = 1 + sum s
-- test run
>> take 5 (inflist sum1)
[1,2,4,8,16]
更新:
如上所述,heads
函数可以替换为 inits
,我不知道它的存在。
gen f = xs where xs = map f $ inits xs
或者
gen f = fix $ map f . inits
我想定义一个无限列表,其中每个元素都是前面所有元素的函数。
因此,列表的第 n+1
个元素将是 f [x1, x2, ..., xn]
。
这看起来很简单,但我似乎无法理解如何去做。有人可以帮忙吗?
您可以使用 unfoldr
:
import Data.List
gen :: ([a] -> a) -> a -> [a]
gen f init = unfoldr (\l -> let n = f (reverse l) in (Just (n, n:l))) [init]
请注意,每次都必须反转输入列表。您可以使用 Data.Sequence
代替:
import Data.Sequence
genSeq :: (Seq a -> a) -> a -> Seq a
genSeq f init = unfoldr (\s -> let n = f s in (Just (n, s |> n))) (singleton init)
作为另一个答案的替代方案,希望它更具可读性但不那么简洁:
-- "heads f" will generate all of the the prefixes of the inflist
heads f = map ( (flip take) (inflist f) ) [1..]
-- inflist will generate the infinite list
inflist f = ( f [] ) : map f (heads f)
-- test function
sum1 s = 1 + sum s
-- test run
>> take 5 (inflist sum1)
[1,2,4,8,16]
更新:
如上所述,heads
函数可以替换为 inits
,我不知道它的存在。
gen f = xs where xs = map f $ inits xs
或者
gen f = fix $ map f . inits