Permalink
Browse files

Added some more functions to FingerTree

  • Loading branch information...
1 parent bbaf045 commit d8baf08153def2edb87b85a403badc5020d448ce @alexeyr alexeyr committed Jun 22, 2010
Showing with 63 additions and 1 deletion.
  1. +47 −1 core/src/main/scala/scalaz/FingerTree.scala
  2. +16 −0 tests/src/test/scala/scalaz/FingerTreeTest.scala
@@ -19,6 +19,10 @@ sealed abstract class Finger[V, A] {
def :+>(a: A): Finger[V, A]
+ def |-:(a: A): Finger[V, A]
+
+ def :-|(a: A): Finger[V, A]
+
def lhead: A
def ltail: Finger[V, A]
@@ -44,6 +48,10 @@ case class One[V, A](v: V, a1: A)(implicit r: Reducer[A, V]) extends Finger[V, A
def :+>(a: A) = Two(v snoc a, a1, a)
+ def |-:(a: A) = one(a)
+
+ def :-|(a: A) = one(a)
+
def lhead = a1
def ltail = error("Tail on the digit One")
@@ -67,6 +75,10 @@ case class Two[V, A](v: V, a1: A, a2: A)(implicit r: Reducer[A, V]) extends Fing
def :+>(a: A) = Three(v snoc a, a1, a2, a)
+ def |-:(a: A) = two(a, a2)
+
+ def :-|(a: A) = two(a1, a)
+
def lhead = a1
def ltail = one(a2)
@@ -101,6 +113,10 @@ case class Three[V, A](v: V, a1: A, a2: A, a3: A)(implicit r: Reducer[A, V]) ext
def :+>(a: A) = Four(v snoc a, a1, a2, a3, a)
+ def |-:(a: A) = three(a, a2, a3)
+
+ def :-|(a: A) = three(a1, a2, a)
+
def lhead = a1
def ltail = two(a2, a3)
@@ -140,6 +156,10 @@ case class Four[V, A](v: V, a1: A, a2: A, a3: A, a4: A)(implicit r: Reducer[A, V
def :+>(a: A) = error("Digit overflow")
+ def |-:(a: A) = four(a, a2, a3, a4)
+
+ def :-|(a: A) = four(a1, a2, a3, a)
+
def lhead = a1
def ltail = three(a2, a3, a4)
@@ -229,6 +249,20 @@ sealed abstract class FingerTree[V, A](implicit measurer: Reducer[A, V]) {
def fold[B](empty: V => B, single: (V, A) => B, deep: (V, Finger[V, A], => FingerTree[V, Node[V, A]], Finger[V, A]) => B): B
+ def |-:(a: A): FingerTree[V, A] = {
+ fold(
+ v => throw new UnsupportedOperationException("Replacing first element of an empty FingerTree"),
+ (v, b) => single(a),
+ (v, pr, m, sf) => deep(a |-: pr, m, sf))
+ }
+
+ def :-|(a: A): FingerTree[V, A] = {
+ fold(
+ v => throw new UnsupportedOperationException("Replacing last element of an empty FingerTree"),
+ (v, b) => single(a),
+ (v, pr, m, sf) => deep(pr, m, sf :-| a))
+ }
+
def <+:(a: A): FingerTree[V, A] = {
implicit val nm = NodeMeasure[A, V]
fold(
@@ -466,7 +500,7 @@ sealed abstract class FingerTree[V, A](implicit measurer: Reducer[A, V]) {
def split1(pred: V => Boolean): (FingerTree[V, A], A, FingerTree[V, A]) = split1(pred, measurer.monoid.zero)
private def split1(pred: V => Boolean, accV: V): (FingerTree[V, A], A, FingerTree[V, A]) = fold(
- v => throw new IllegalArgumentException, // we can never get here
+ v => throw new UnsupportedOperationException("Splitting an empty FingerTree"), // we can never get here
(v, x) => (empty, x, empty),
(v, pr, m, sf) => {
val accVpr = accV snoc pr
@@ -511,6 +545,18 @@ sealed abstract class FingerTree[V, A](implicit measurer: Reducer[A, V]) {
case _ => OnR(deep(pr, m, sf.rtail), sf.rhead)
})
+ def lheadOption: Option[A] = fold(
+ v => None,
+ (v, x) => Some(x),
+ (v, pr, m, sf) => Some(pr.lhead)
+ )
+
+ def rheadOption: Option[A] = fold(
+ v => None,
+ (v, x) => Some(x),
+ (v, pr, m, sf) => Some(sf.rhead)
+ )
+
def map[B, V2](f: A => B)(implicit m: Reducer[B, V2]): FingerTree[V2, B] = {
implicit val nm = NodeMeasure[B, V2]
fold(
@@ -38,4 +38,20 @@ class FingerTreeTest extends Specification with Sugar with ScalaCheck {
val splitTree = tree.split(_ > index)
(splitTree._1.toStream, splitTree._2.toStream) ≟ asStream.splitAt(index)
}
+
+ "replacing last element works correctly" verifies {(tree: SequenceTree[Int], x: Int) =>
+ tree.isEmpty || ((tree :-| x).toStream ≟ (tree.toStream.init :+ x))
+ } // can't use conditional property here, it would be better to write !tree.isEmpty ==> ...
+
+ "replacing first element works correctly" verifies {(tree: SequenceTree[Int], x: Int) =>
+ tree.isEmpty || ((x |-: tree).toStream ≟ (x +: tree.toStream.tail))
+ }
+
+ "lheadOption works correctly" verifies {(tree: SequenceTree[Int]) =>
+ tree.lheadOption ≟ tree.toStream.headOption
+ }
+
+ "rheadOption works correctly" verifies {(tree: SequenceTree[Int]) =>
+ tree.rheadOption ≟ tree.toStream.lastOption
+ }
}

0 comments on commit d8baf08

Please sign in to comment.