A "difference list" - A List like structure with O(1) appends.
A Double-ended queue, based on the Bankers Double Ended Queue as described by C.
A Double-ended queue, based on the Bankers Double Ended Queue as described by C. Okasaki in "Purely Functional Data Structures"
A queue that allows items to be put onto either the front (cons) or the back (snoc) of the queue in constant time, and constant time access to the element at the very front or the very back of the queue. Dequeueing an element from either end is constant time when amortized over a number of dequeues.
This queue maintains an invariant that whenever there are at least two elements in the queue, neither the front list nor back list are empty. In order to maintain this invariant, a dequeue from either side which would leave that side empty constructs the resulting queue by taking elements from the opposite side
Discrete Interval Encoding Tree (Diet).
Discrete Interval Encoding Tree (Diet). It stores subsets of types having a total order, a predecessor and a successor function described by Enum[A]
Diet is a binary search tree where each node contains a range of values and the set of all nodes is a set of disjoint sets.
In the best case, when there are no "holes" in the stored set, the interval representation consists of just one single interval (node) and finding, inserting and deleting operations are O(1). In the worse case, where there are not two adjacent elements in the set, the representation is equivalent to a binary search tree.
Represent discrete operations that can be performed on A
Binary Heap
Binary Heap
Normally, binary heaps are not common the functional environments since they implementationis based on mutable arrays. However, this implementation is purely functional, based on the VLADIMIR KOSTYUKOV paper.
It is important to note that we can, in fact, to create the Binary Heap in order O(n) from a List
using the function
heapify
.
An intensional set, which is a set which instead of enumerating its elements as a extensional set does, it is defined by a predicate which is a test for membership.
Immutable, singly-linked list implementation.
Immutable, singly-linked list implementation.
This code is very similar to scala.List, with a few key differences:
1. It does not expose any "unsafe" methods. 2. It is invariant, whereas scala.List is covariant. 3. It uses subtyping to differentiate non-emptiness.
The types defined here are as follows:
(Every List[A] is either a Nel[A] or an El[A].)
While it does not provide every single Scala collection method, it provides a decent number of them.
A tree based immutable Map.
An optional value
An optional value
An Option[A]
will either be a wrapped A
instance (Some[A]
),
or a lack of underlying A
instance (None[A]
).
Option[A]
is isomorphic to the Option in the Scala standard
library, however there are some differences between the two. This
Option
is invariant in A
while the standard library Option
is
covariant. This Option
does not expose an unsafe get
operation
to access the underlying A
value (that may not exist) like the
standard library version does. This Option
does not come with an
implicit conversion to Iterable
(a trait with over a dozen super
types).
Represent a range [x, y] that can be generated by using discrete operations
An immutable, ordered, extesntional Set
An immutable, ordered, extesntional Set
This datastructure maintains balance using the [AVL](https://en.wikipedia.org/wiki/AVL_tree) algorithm.
Streaming[A]
represents a stream of values.
Streaming[A]
represents a stream of values. A stream can be
thought of as a collection, with two key differences:
.length
method.2. It may be lazy. In other words, the entire stream may not be in memory. In this case, each "step" of the stream has instructions for producing the next step.
Streams are not necessarily lazy: they use Eval[Streaming[A]]
to
represent a tail that may (or may not be) lazy. If now[A]
is used
for each tail, then Streaming[A]
will behave similarly to
List[A]
. If Later[A]
is used for each tail, then Streaming[A]
will behave similarly to scala.Stream[A]
(i.e. it will
lazily-compute the tail, and will memoize the result to improve the
performance of repeated traversals). If always[A]
is used for
each tail, the result will be a lazy stream which does not memoize
results (saving space at the cost of potentially-repeated
calculations).
Since Streaming[A]
has been compared to scala.Stream[A]
it is
worth noting some key differences between the two types:
Streaming[A]
can represent it more efficiencly, using now[A]
, rather than
allocating a list of closures. 2. Streaming[A]
does not memoize by default. This protects
against cases where a reference to head will prevent the entire
stream from being garbage collected, and is a better default.
A stream can be memoized later using the .memoize
method.
3. Streaming[A]
does not inherit from the standard collections,
meaning a wide variety of methods which are dangerous on
streams (.length
, .apply
, etc.) are not present.
4. scala.Stream[A]
requires an immediate value for .head
. This
means that operations like .filter
will block until a
matching value is found, or the stream is exhausted (which
could be never in the case of an infinite stream). By contrast,
Streaming[A]
values can be totally lazy (and can be
lazily-constructed using Streaming.defer()
), so methods like
.filter
are completely lazy.
5. The use of Eval[Streaming[A]]
to represent the "tail" of the
stream means that streams can be lazily (and safely)
constructed with Foldable#foldRight
, and that .map
and
.flatMap
operations over the tail will be safely trampolined.
A "difference list" - A List like structure with O(1) appends. Based on
Data.DList
, a Haskell library by Don Stewart.