Cameron Martin
Cameron Martin

Reputation: 6010

Compute next element of list based on previous elements

I want to define an infinite list where each element is a function of all the previous elements.

So, the n+1th element of the list would be f [x1, x2, ..., xn].

This seems simple, but I cannot seem to get my head around how to do it. Can anyone help?

Upvotes: 6

Views: 1181

Answers (3)

effectfully
effectfully

Reputation: 12735

gen f = xs where xs = map f $ inits xs

Or

gen f = fix $ map f . inits

Upvotes: 11

Lee
Lee

Reputation: 144206

You can use 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]

note this has to reverse the input list each time. You could use Data.Sequence instead:

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)

Upvotes: 2

Eugene Sh.
Eugene Sh.

Reputation: 18381

As an alternative to the other answer, hopefully a little more readable but less laconic:

-- "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]

Upd: As pointed above the heads function can be replaced with inits, which I wasn't aware of it's existence.

Upvotes: 4

Related Questions