packages feed

persistent-vector-0.1.0.0: README.md

# Persistent Vector

A library providing persistent (purely functional) vectors for Haskell
based on array mapped tries.

## Description

These persistent vectors are modeled on the persistent vector used by
clojure, with an API modeled after Data.Sequence from the containers
library.  This data structure is *spine strict* and is not useful for
incremental consumption.  If you need that, stick to lists.  It is
still lazy in the elements.

While per-element operations are O(log(n)), the internal tree can
never be more than 7 or 8 deep.  Thus, they are effectively constant
time.

This implementation adds O(1) slicing support for vectors that I do
not believe clojure supports.  The implementation cheats, though, and
slices can retain references to objects that cannot be indexed.

## Performance

Performance is an important consideration for a data structure like
this.  The package contains a criterion benchmark suite that attempts
to compare the performance of persistent vectors against a variety of
existing persistent data structures.  As an overview of the results I
have observed:

 * Traversing and building lists is faster than the same operations
   with persistent vectors.

 * (Strict) left folds over persistent vectors are faster than left
   folds over Sequences.  Right folds over Sequences are faster than
   right folds over vectors.

 * Indexing persistent vectors is faster than indexing sequences and
   IntMaps (and, of course, lists).

 * Appending to vectors is slightly faster than appending to a Sequence.
   It is much faster than appending to an IntMap.

 * Updating an element at an index in a vector is *slower* than
   updating an index in a Sequence (but still faster than an IntMap).

Overall, it seems like persistent vectors are efficient at most tasks.
If you only need a (strict) left fold, they are efficient for
traversal.  Indexing and construction are very fast, but Sequences are
superior for element-wise updates.

## Implementation

## TODO

 * More of the Data.Sequence API

 * More efficient Eq and Ord instances.  This is tricky in the
   presence of slicing.  There are faster implementations for unsliced
   inputs.

 * Implement something to make parallel reductions simple (maybe
   something like vector-strategies)

 * Implement cons.  Cons can use the space that is hidden by the
   offset cheaply.  It can also make a variant of pushTail
   (pushHead) that allocates fragments of preceeding sub-trees.
   Each cons call will modify the offset of its result vector.