A combination of a list and a lazy list.
Put two streams together into one stream such that you will be able to eventually access any element from either stream, regardless if the first stream is infinite, the second stream is infinite, or both streams are infinite.
evensLessThan10 =
Cons 0 (Cons 2 (Cons 4 (Cons 6 (Cons 8 Empty))))
oddsLessThan10 =
Cons 1 (Cons 3 (Cons 5 (Cons 7 (Cons 9 Empty))))
take 10 (append evensLessThan10 oddsLessThan10) == [ 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 ]
arithmeticProgression a d =
Cons a <| Suspend (\_ -> arithmeticProgression (a + d) d)
evens =
arithmeticProgression 0 2
odds =
arithmeticProgression 1 2
naturals =
append evens odds
take 10 (append evensLessThan10 odds) == [ 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 ]
take 10 (append evens oddsLessThan10) == [ 0, 1, 3, 5, 7, 9, 2, 4, 6, 8 ]
take 10 naturals == [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]N.B. In the last example, the two infinite streams are completely interleaved. append is the basis upon which
it is said that miniKanren uses a complete interleaving search.
Map a function over a stream and append the resulting streams.
repeat n =
Cons n <| Suspend (\_ -> repeat n)
take 100 (appendMap repeat naturals) == [ 0, 0, 1, 0, 0, 1, 0, 2, 0, 1, 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0 ]
type alias Occurrences =
Int
statistics : List ( Int, Occurrences )
statistics =
[ ( 0, 53 )
, ( 1, 26 )
, ( 2, 12 )
, ( 3, 6 )
, ( 4, 2 )
, ( 5, 1 )
]N.B. It takes a while to get to each number but each number will eventually be reached, thanks to how append works.
If you remove the
Suspendconstructor then you have a list.If you combine the
ConsandSuspendconstructors then you have a lazy list.Normal list streams:
Partial lazy list streams:
A full lazy list stream: