From 2676ecbfbf5d8296944abebc520056a8629a1157 Mon Sep 17 00:00:00 2001 From: Alexey Filippov Date: Sat, 4 May 2019 10:07:57 +0100 Subject: [PATCH] #4 - Initial draft of finger tree structures (WIP) --- src/main/scala/finger/Fingers.scala | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/main/scala/finger/Fingers.scala diff --git a/src/main/scala/finger/Fingers.scala b/src/main/scala/finger/Fingers.scala new file mode 100644 index 0000000..5d9ddae --- /dev/null +++ b/src/main/scala/finger/Fingers.scala @@ -0,0 +1,68 @@ +package finger + +import scala.language.higherKinds + +object Fingers { + + // ========================================================================================== + sealed trait FingerTree[+A] + + case object Empty extends FingerTree[Nothing] + + case class Single[A](a: A) extends FingerTree[A] + + case class Deep[A](l: Digit[A], down: FingerTree[Node[A]], r: Digit[A]) extends FingerTree[A] + + // ========================================================================================== + sealed trait Node[A] + + case class Node2[A](a: A, b: A) extends Node[A] + + case class Node3[A](a: A, b: A, c: A) extends Node[A] + + // ========================================================================================== + type Digit[A] = List[A] + + // ========================================================================================== + trait Reduce[F[_]] { + def reducer[A, B](fn: (A, B) => B): (F[A], B) => B + + def reducel[A, B](fn: (B, A) => B): (B, F[A]) => B + } + + implicit val listReduce: Reduce[List] = new Reduce[List] { + override def reducer[A, B](fn: (A, B) => B): (List[A], B) => B = (as, b) => as.foldRight(b)(fn) + + override def reducel[A, B](fn: (B, A) => B): (B, List[A]) => B = (b, as) => as.foldLeft(b)(fn) + } + + def toList[A, F[_] : Reduce](s: F[A]): List[A] = + implicitly[Reduce[F]].reducer[A, List[A]](_ :: _)(s, Nil) + + // ========================================================================================== + implicit val nodeReduce: Reduce[Node] = new Reduce[Node] { + override def reducer[A, B](fn: (A, B) => B): (Node[A], B) => B = (na, z) => na match { + case Node2(a, b) => fn(a, fn(b, z)) + case Node3(a, b, c) => fn(a, fn(b, fn(c, z))) + } + + override def reducel[A, B](fn: (B, A) => B): (B, Node[A]) => B = (z, na) => na match { + case Node2(a, b) => fn(z, fn(b, a)) + case Node3(a, b, c) => fn(fn(fn(z, c), b), a) + } + } + + implicit val fingerTreeReduce: Reduce[FingerTree] = new Reduce[FingerTree] { + override def reducer[A, B](fn: (A, B) => B): (FingerTree[A], B) => B = (fta, z) => fta match { + case Empty => z + case Single(a) => fn(a, z) + case Deep(pr, m, sf) => ??? + } + + override def reducel[A, B](fn: (B, A) => B): (B, FingerTree[A]) => B = (z, fta) => fta match { + case Empty => z + case Single(a) => fn(z, a) + case Deep(pr, m, sf) => ??? + } + } +}