FR
importPour l'utiliser : import Data.LazyList

LazyList — possibly-infinite lists with lazy, memoised tails

Synopsis
data LazyList a
  = Nil
  | a :: Lazy (LazyList a)

A list whose tail is evaluated only on demand and then remembered (memoised), so it may be infinite. It shares the constructors Nil and :: with the strict Prelude List: the compiler resolves which is meant from the type, so list syntax ([1, 2, 3]), the cons operator (x :: xs) and pattern matching read exactly as for List — only the tail differs in being lazy (Lazy (LazyList a)).

Every operation here has the signature of its strict List twin, with LazyList in place of List (take : Nat -> LazyList a -> LazyList a, as take : Nat -> List a -> List a). So a plain import Data.LazyList is enough: both versions stay in scope and the TYPE decides which one is meant; turning a List program into a LazyList one means changing the types, not the code. (A test keeps the two libraries in agreement.)

Nil

the empty lazy list

::

a head in front of a tail computed on demand

repeat : a -> LazyList a

repeat x is the infinite list x, x, x, ….

iterate : (a -> a) -> a -> LazyList a

iterate f x is x, f x, f (f x), ….

from : Int -> LazyList Int

The integers from n upward: n, n+1, n+2, ….

enumFromTo : Enum a => a -> a -> LazyList a

[lo .. hi] : lo, succ lo, …, hi. enumDist lo hi (unit steps from lo up to hi) is 0 both for [a .. a] and for an empty [b .. a] ; the two are told apart by enumDist hi lo, 0 only when hi == lo.

enumFromToExcl : Ord a => Enum a => a -> a -> LazyList a

[lo .. hi[ (or [lo .. hi)) : up to but EXCLUDING hi ; empty when hi <= lo.

enumFromThenTo : Ord a => Enum a => a -> a -> a -> LazyList a

[a, b .. c] : a, then a step of b - a at a time, while within the bound c (inclusive). Direction from a vs b ; step 0 refused, as for List.

enumFrom : Enum a => a -> LazyList a

[e ..] : the range e, succ e, … with no bound — only a LazyList can hold it. It stops where the TYPE stops (KB-200) : never on Int or Nat, at U+10FFFF on Char.

enumFromThen : Ord a => Enum a => a -> a -> LazyList a

[a, b ..] : the stepped range a, a + (b - a), … with no bound. Step 0 is refused as for List ; the direction is read from a vs b, and the range stops where the type stops — [5, 3 ..] : LazyList Nat is 5, 3, 1 then ends, [10, 8 ..] : LazyList Int never ends.

take : Nat -> LazyList a -> LazyList a

take n xs is the first n elements (fewer if the list is shorter), still LAZY: elements are produced one by one as the result is consumed (head (take 1000000 xs) forces ONE cell). Like Haskell's take and Idris's lazy operations — a take that returned a strict List would force n cells at the call, defeating the point of a lazy pipeline. For a strict List, convert with toList. n : Nat, the same count type as length.

drop : Nat -> LazyList a -> LazyList a

drop n xs discards the first n elements (forcing them to reach the suffix), and returns the still-lazy remainder.

takeWhile : (a -> Bool) -> LazyList a -> LazyList a

The longest prefix whose elements satisfy p, still LAZY (produced as consumed, like take).

toList : LazyList a -> List a

Force the WHOLE lazy list into a strict List — the explicit conversion (diverges on an infinite list; pair it with take/takeWhile first).

concatMap : (a -> LazyList b) -> LazyList a -> LazyList b

Map each element to a LazyList and concatenate the results, lazily. List comprehensions [ e | x <- xs, … ] over a LazyList use this, so they stay lazy and may SHORT-CIRCUIT: consuming only head (or take 1) of the result forces only as much of the input as needed to produce the first element.

STACK-SAFE: skipping arbitrarily many empty mappings (the deep search of an [ e | … ] that short-circuits late) runs in O(1) stack instead of overflowing.

zipWith : (a -> b -> c) -> LazyList a -> LazyList b -> LazyList c

zipWith f xs ys combines elements pairwise, stopping at the shorter list.

foldr : (a -> b -> b) -> b -> LazyList a -> b

Right fold, STRICT in the accumulator: oppi evaluates arguments before the call, so f receives the already-folded rest — this ALWAYS traverses the whole list and DIVERGES on an infinite one (unlike Haskell's foldr, whose laziness lets f stop early). For an early-exit fold, use foldrLazy.

foldrLazy : (a -> Lazy b -> b) -> Lazy b -> LazyList a -> b

Right fold that can stop (the twin of List.foldrLazy, and the LazyList definition of the Foldable method): f receives the fold of the tail suspended (Lazy b), so the fold stops as soon as f does not read it, and terminates on an infinite list; the seed z is read only if the fold reaches the end. foldrLazy (&&) True (repeat False) is False.

any : (a -> Bool) -> LazyList a -> Bool

Is p true of SOME element? Stops at the first hit — any p xs on an infinite xs terminates as soon as a witness appears.

all : (a -> Bool) -> LazyList a -> Bool

Is p true of EVERY element? Stops at the first counter-example.

find : (a -> Bool) -> LazyList a -> Maybe a

The first element satisfying p, if any (stops there).

elem : Eq a => a -> LazyList a -> Bool

Is x an element? Stops at the first occurrence.

length : LazyList a -> Nat

The number of elements, as a Nat — FORCES the whole list (diverges on an infinite one); observe an infinite list through take first.

foldl : (b -> a -> b) -> b -> LazyList a -> b

Left fold. Diverges on an infinite list (it must reach the end).

isEmpty : LazyList a -> Bool

Is the list empty? Forces only the first cell.

reverse : LazyList a -> LazyList a

The list in reverse order — FORCES the whole list.

dropWhile : (a -> Bool) -> LazyList a -> LazyList a

The remainder after the longest prefix whose elements satisfy p (the companion of takeWhile).

replicate : Nat -> a -> LazyList a

n copies of a value.

sum : Additive a => LazyList a -> a

Sum of the elements (0 for the empty list) — FORCES the whole list.

product : Multiplicative a => LazyList a -> a

Product of the elements (1 for the empty list) — FORCES the whole list.

elemBy : (a -> a -> Bool) -> a -> LazyList a -> Bool

Is an element present, using a supplied equality test? Stops at the first occurrence.

lookup : Eq k => k -> LazyList (k, v) -> Maybe v

Look up a key in an association list (stops at the first match).

mapMaybe : (a -> Maybe b) -> LazyList a -> LazyList b

Apply a partial function to every element, keeping the successes, lazily.

intersperse : a -> LazyList a -> LazyList a

Insert sep between consecutive elements, lazily.

intercalate : Monoid m => m -> LazyList m -> m

Join monoid values, inserting sep between consecutive elements — FORCES the whole list.

findIndex : (a -> Bool) -> LazyList a -> Maybe Nat

The 0-based index of the first element satisfying the predicate (stops there).

elemIndex : Eq a => a -> LazyList a -> Maybe Nat

The 0-based index of the first occurrence of a value (stops there).

span : (a -> Bool) -> LazyList a -> (LazyList a, LazyList a)

(longest prefix all satisfying p, the remainder) = (takeWhile p xs, dropWhile p xs).

break : (a -> Bool) -> LazyList a -> (LazyList a, LazyList a)

The prefix up to the first element satisfying p, and the rest: break p = span (not . p).

insertOrd : Ord a => a -> LazyList a -> LazyList a

Insert into a sorted list, keeping it sorted (lazily past the insertion).

insertBy : (a -> a -> Ordering) -> a -> LazyList a -> LazyList a

Insert with a supplied comparator, keeping the list sorted.

sort : Ord a => LazyList a -> LazyList a

Sort into ascending order (stable insertion sort) — FORCES the whole list.

sortBy : (a -> a -> Ordering) -> LazyList a -> LazyList a

Sort by a supplied comparator (stable) — FORCES the whole list.

sortOn : Ord b => (a -> b) -> LazyList a -> LazyList a

Sort by a key projection, computing each key once — FORCES the whole list.

nubBy : (a -> a -> Bool) -> LazyList a -> LazyList a

Remove duplicates using a supplied equality, keeping the first occurrence, lazily.

nub : Eq a => LazyList a -> LazyList a

Remove duplicates (by ==), keeping the first occurrence, lazily.

scanl : (b -> a -> b) -> b -> LazyList a -> LazyList b

Left scan: the running accumulator after each step, seeded with z, lazily (one longer than the input).

scanr : (a -> b -> b) -> b -> LazyList a -> LazyList b

Right scan (always non-empty) — FORCES the whole list.

unfoldr : (b -> Maybe (a, b)) -> b -> LazyList a

Build a list from a seed, lazily: f returns Just (element, next seed) to emit, or Nothing to stop (it may never stop).

foldl1 : (a -> a -> a) -> LazyList a -> Maybe a

Left fold over a NON-empty list, seeded with its first element; Nothing for the empty list — FORCES the whole list.

foldr1 : (a -> a -> a) -> LazyList a -> Maybe a

Right fold over a NON-empty list; Nothing for the empty list — FORCES the whole list.

isPrefixOf : Eq a => LazyList a -> LazyList a -> Bool

Is the first list a prefix of the second? Stops at the first difference.

isSuffixOf : Eq a => LazyList a -> LazyList a -> Bool

Is the first list a suffix of the second? FORCES both lists.

isInfixOf : Eq a => LazyList a -> LazyList a -> Bool

Is the first list a contiguous sub-sequence of the second? Stops at the first occurrence.

index : LazyList a -> Nat -> a

Direct subscript xs[i] — panics if i is out of range.

set : LazyList a -> Nat -> a -> LazyList a

set xs i v — the list with position i set to v (unchanged if i is out of range), lazily.