{- | "Data.Random.Choose" provides an efficient mechanism to select /n/ items uniformly at random from an input stream, for some fixed /n/. * "Data.Random.Choose.Tree" contains the implementation details. * "Data.Random.Choose.IO" puts everything together as a single function (using IO). -} module Data.Random.Choose ( -- * Algorithm outline -- $outline ) where import Data.Random.Choose.IO import Data.Random.Choose.Tree {- $outline We store items on a binary tree ('Tree'), moving them down the left or right branch according to a coin flip. At the end, the rightmost /n/ items on the tree are selected. Each time we 'insert' into a tree having /n/ items, we prune its leftmost item ('applyLimit' and 'evict'). It may be helpful to think of this as lazily assigning each item a /d/-bit score, where /d/ is the maximum depth of the tree. Moving an item to the left or right corresponds to appending a 0 or 1 to its score. Note that the laziness is necessary, because /d/ is not known a priori. The process of moving items futher down the tree is referred to as disambiguation ('disambiguate') because its purpose is to resolve ties in the score. -}