---
title: Seekable Iterator Interface
url: https://www.emergentmind.com/topics/seekable-iterator-interface
type: topic
---

# Seekable Iterator Interface

Searching arXiv for the specified paper to ground the article in the primary source.
A seekable iterator interface is a two-operation abstraction for data sources of key–value pairs in strictly increasing key order. In "Fair intersection of seekable iterators" [2510.26016], the interface consists of `posn` and `seek`, and its central purpose is to realize fairness via bounded work: every single call to `seek(s, p)` does only a bounded amount of work before returning a new `Seek` node. The paper presents this interface as the basis of a fair intersection primitive and as an elegant compositional approach to implementing worst-case optimal joins, suitable for shallow embedding in functional languages [2510.26016].

## 1. Core interface and operational meaning

The interface regards a data source of key–value pairs, in strictly increasing key order, as exposing exactly two operations:

- `posn : Seek k v → Position k v`
- `seek : Seek k v × Bound k → Seek k v`

The associated Haskell-style pseudocode is:

```haskell
data Bound k
  = Atleast k      -- we require k' ≥ k
  | Greater k      -- we require k' >  k
  | Done           -- no further keys

data Position k v
  = Found k v       -- I am currently at (k,v)
  | BoundP (Bound k)  -- I can only promise that future keys ≥ this bound

data Seek k v = Seek
  { posn :: Position k v
  , seek :: Bound k -> Seek k v
  }
```

The operational interpretation is explicit. `posn(s) = Found k v` means that the next key–value pair is `(k,v)`. `posn(s) = BoundP p` means that there is no pair right now, but all future keys in `s` are guaranteed to satisfy the predicate `p`. The operation `seek(s, p)` “rewinds” or advances `s` to the smallest element satisfying bound `p`, or becomes `BoundP Done` if no such element exists [2510.26016].

The paper also introduces the derived form

```haskell
bound(s) := case posn(s) of
              Found k _ -> Atleast k
              BoundP p  -> p
```

This makes precise the fact that whenever `s.posn = Found k`, all future keys are at least `k`. A common misunderstanding would be to read the abstraction as a conventional next-only stream. The formulation in the paper is narrower and more specific: it replaces the traditional “next-only” stream interface with a two-operation interface, `posn + seek`, and ties fairness to the guarantee that each `seek` call returns after bounded work [2510.26016].

## 2. Semantics, invariants, and order structure

The interface is constrained by four correctness properties.

First, **monotonicity of bounds** requires that for all bounds $p_1 \le p_2$,

$$
\mathrm{seek}(\mathrm{seek}(s, p_1), p_2) \equiv \mathrm{seek}(s, p_2).
$$

Second, **correctness of `posn` vs. `seek`** requires that if `posn(s)=Found k v` then `k` satisfies whatever bound was last given to `s`; if `posn(s)=BoundP p` then no future key in `s` can violate `p`. Third, **idempotence** is stated as the condition that the iterator never “goes backwards”: once `seek(s, p)` has been performed, the iterator remains at or past all keys less than `p`. Fourth, **sortedness** states that `toSorted(s)`, obtained by repeatedly extracting `Found` and then calling `seek` with `Greater k`, coincides with the underlying true data in increasing order [2510.26016].

The order on bounds is defined semantically: $p_1 \le p_2$ iff every key satisfying $p_2$ also satisfies $p_1$. Concretely:

- `Atleast a ≤ Atleast b` iff `a ≤ b`
- `Atleast a ≤ Greater b` iff `a < b`
- `Greater a ≤ Atleast b` iff `a < b`
- `Greater a ≤ Greater b` iff `a < b`
- `_ ≤ Done` iff `false`
- `Done ≤ Done` iff `true`

The least upper bound under this order is written `max(p₁,p₂)` [2510.26016].

This order structure is not incidental. It is the mechanism by which partial information from multiple iterators can be merged compositionally. A plausible implication is that the interface is designed not merely to expose current position, but to expose lower-bound knowledge that can be propagated across intersections and nested joins.

## 3. Fairness as bounded work

The paper places fairness at the center of the interface. Its starting point is the observation that miniKanren’s key semantic advance over Prolog is to implement a complete yet efficient search strategy, fairly interleaving execution between disjuncts, and that this fairness is accomplished by bounding how much work is done exploring one disjunct before switching to the next. The same idea—fairness via bounded work—is then used for seekable iterators [2510.26016].

The decisive guarantee is that every single call to `seek(s, p)` does only a bounded amount of work before returning a new `Seek` node. If the underlying data structure supports `seek(s, p)` in time `O(log |s| + 1)`, with galloping search in a sorted array or `O(log n)` in a balanced tree as examples, then a single two-way intersection step `intersect(s,t).seek(p)` performs at most one `seek` on `s` and one `seek` on `t` [2510.26016].

In an $n$-ary nested intersection, each sub-iterator gets at most one `seek` per `intersect` invocation. No one sub-iterator can do unbounded work before the others get scheduled. The paper states that if `s,t` have sizes `n,m` and seek-cost is `O(log n), O(log m)`, then each call to `intersect(s,t)` or `toSorted(intersect(s,t))` performs at most

$$
O(\log n + \log m)
$$

work, and the total work to enumerate `k` output tuples is

$$
O\bigl(k \cdot (\log n + \log m)\bigr).
$$

By generalizing to $k$-way intersection, the total cost is proportional to

$$
O\Bigl(\Bigl(\sum_{i=1}^k \log N_i\Bigr) \cdot |Output|\Bigr),
$$

which the paper states matches the usual worst-case optimal join bound of Ngo et al. up to these logarithmic factors [2510.26016].

This fairness notion is therefore scheduling-theoretic as well as asymptotic. It is not merely that the algorithm is efficient in aggregate; it is that the interface forbids an implementation strategy in which one component iterator monopolizes work before control returns to the rest.

## 4. Intersection and compositional join construction

The paper uses the interface to support worst-case-optimal joins compositionally. In a relational join of $k$ attributes, each relation is represented as a trie of depth $k$:

$$
R \subseteq A_1 \times A_2 \times \dots \times A_k
\;\mapsto\;
\mathrm{Seek}\ a_1\ (\mathrm{Seek}\ a_2\ (\dots \mathrm{Seek}\ a_k\ () \dots)).
$$

Join evaluation proceeds by successively intersecting all top-level iterators on attribute $A_1$, then for each matching key filtering the nested `Seek` on $A_2$, and so on. Because each intersection is fair, two conditions hold: no single two-way intersection can “hog” the predicate bound, and bounds from all relations are propagated together [2510.26016].

The resulting behavior is identified with Veldhuizen’s Leapfrog Triejoin, but obtained compositionally by simply nesting pairwise intersections:

$$
\mathrm{intersect}_3(R,S,T) \;\coloneqq\; \mathrm{intersect}(R,\mathrm{intersect}(S,T)).
$$

The crucial property is that all bounds are `max`-ed at each layer, so deeper levels can skip ahead immediately to the global lower bound, rather than waiting for one sub-intersection to fully materialize before exchanging bounds [2510.26016].

This compositionality is one of the article’s main conceptual claims. Traditional presentations of multiway join algorithms often foreground bespoke $k$-way operators. Here, by contrast, nested 2-way intersects behave exactly like an optimal $k$-way intersection. This suggests that the paper’s contribution is as much about interface design as about algorithm design: the interface makes fair multiway behavior emerge from local pairwise composition.

## 5. Correctness results and performance theorems

The paper states two principal results.

**Theorem 1 (Soundness & Completeness).** For any two seekables `s,t`,

$$
\mathrm{toList}\bigl(\mathrm{intersect}(s,t)\bigr)
\;=\;
\mathrm{listIntersect}(\mathrm{toList}(s),\,\mathrm{toList}(t)),
$$

where `listIntersect` is the ordinary sorted-list intersection [2510.26016].

**Theorem 2 (Per-Step Fairness).** Let `seekCost(s)` denote the maximum work done by `seek(s, ·)`. Then every call

`intersect(s,t).seek(p)`

invokes at most one call to `s.seek(·)` and one call to `t.seek(·)`. In particular,

$$
\mathrm{cost}\bigl(\mathrm{seek}(\mathrm{intersect}(s,t),p)\bigr)
\;\le\;
\mathrm{seekCost}(s)\;+\;\mathrm{seekCost}(t).
$$

The stated corollary is that if each `seek` on a data source of size `N` costs `O(log N)`, then each intersection step costs `O(log N)`, and enumerating `k` output tuples costs `O(k \cdot \log N)` [2510.26016].

These results separate two dimensions of the interface. The first theorem establishes extensional correctness: the enumerated output is exactly the ordinary intersection of the underlying sorted sequences. The second theorem establishes intensional discipline: each step of the composed iterator preserves the bounded-work property of its constituents. Taken together, these are the basis for the summary claim that the formal statements guarantee both correctness and performance [2510.26016].

## 6. Representative implementations and usage patterns

The paper includes Haskell-style code sketches for building seekables and using them in joins. A seekable may be constructed from a sorted array:

```haskell
fromSortedArray
  :: (Ix i, Integral i, Ord k)
  => Array i (k,v) -> Seek k v
fromSortedArray arr = go (lo,hi) where
  (lo,hi) = bounds arr
  go (l,u) =
    let posn | l>u     = BoundP Done
             | otherwise =
                 let (k,v)=arr!l
                 in  Found k v
        seek BDone      = Seek (BoundP Done) (\_→ Seek (BoundP Done) id)
        seek (Atleast t)= go (gallop (≥t) (l+1) u)
        seek (Greater t)= go (gallop (> t) (l+1) u)
    in  Seek posn seek
```

Two-way intersection is defined as follows:

```haskell
intersect
  :: Ord k
  => Seek k a -> Seek k b -> Seek k (a,b)
intersect s t = Seek posn' seek' where
  posn' = case (posn s, posn t) of
    (Found k x, Found k' y)
      | k==k'    -> Found k (x,y)
    _            -> BoundP (bound s `max` bound t)
  seek' b = intersect (seek s b) (seek t b)
```

For a three-way join on `key1`, the sketch is:

```haskell
join3key1 R S T = toList
  $ intersect R (intersect S T)
```

For a full natural join `R ⋈ S` on two attributes `(k₁,k₂)`, the sketch is:

```haskell
joinOn2 (R :: Seek k₁ (Seek k₂ v₁))
        (S :: Seek k₁ (Seek k₂ v₂))
  = [ ((k₁,k₂), (v₁,v₂))
    | Seek (Found k₁ innerR) _   <- [R `intersect` S]
    , Seek (Found k₂ x) _        <- [innerR `intersect` y]
    ]
  where y = seek S (Atleast k₁)
```

The paper comments that, desugared, this is just two nested pairwise intersects, each propagating the max of all bounds, and yielding exactly the same behavior as a full 2-attribute “leapfrog triejoin” [2510.26016].

These sketches are significant because they situate the interface in a shallow-embedded Haskell setting rather than presenting it as a specialized runtime primitive. A plausible implication is that the paper treats seekability as a reusable denotational and operational interface, not merely as a one-off join kernel.

## 7. Conceptual significance and scope

The summary given in the paper isolates three outcomes of the interface design. By replacing the traditional next-only stream interface with `posn + seek`, and requiring that each `seek(_,_)` do only a bounded amount of work before returning control, one obtains a fair intersection primitive, true compositionality, and a straightforward shallow-embedded Haskell implementation suitable for building worst-case-optimal multiway joins by simple nesting [2510.26016].

The connection to miniKanren and Prolog locates the idea in a broader semantics of fair scheduling rather than only in relational query evaluation. The connection to Veldhuizen’s Leapfrog Triejoin locates it in worst-case-optimal join processing. The seekable iterator interface sits between these domains: it is an iterator discipline in which lower-bound information is first-class, composition preserves fairness, and nested binary intersections recover the behavior of multiway join algorithms [2510.26016].

A common misconception would be to regard fairness here as synonymous with symmetry of code structure. The paper’s notion is narrower and more formal: fairness is accomplished by bounding how much work is done before switching, and per-step fairness is expressed by the fact that `intersect(s,t).seek(p)` invokes at most one `seek` on each input. Within the scope stated in the paper, this is the mechanism that underwrites both completeness of enumeration and worst-case-optimal join behavior up to logarithmic factors [2510.26016].

Source: https://www.emergentmind.com/topics/seekable-iterator-interface