Coverage Summary for Class: ListVectorInstances (lzwpack.data)

Class Method, % Line, %
ListVectorInstances 77.8% (7/ 9) 77.8% (7/ 9)
ListVectorInstances$$anon$1 100% (3/ 3) 100% (3/ 3)
ListVectorInstances$$anon$2 100% (3/ 3) 100% (3/ 3)
ListVectorInstances$$anonfun$ListVectorEq$2 100% (1/ 1) 100% (1/ 1)
ListVectorInstances$ListVectorApplicative$ 100% (3/ 3) 100% (3/ 3)
ListVectorInstances$ListVectorTraverse$ 100% (4/ 4) 100% (6/ 6)
total 91.3% (21/ 23) 92% (23/ 25)


1 package lzwpack.data 2  3 import cats.{Applicative, Eq, Eval, Monoid, Show, Traverse, ~>} 4 import lzwpack.data.ListVector.empty 5 import cats.implicits._ 6 import cats.kernel.Hash 7  8 import scala.collection.{GenTraversable, TraversableLike} 9 import scala.collection.generic.{IsSeqLike, IsTraversableLike} 10  11 /** 12  * Defines some generic type class instances for [[ListVector]]. 13  */ 14 trait ListVectorInstances { 15  implicit object ListVectorTraverse extends Traverse[ListVector] { 16  override def traverse[F[_]: Applicative, A, B](fa: ListVector[A])(f: A => F[B]): F[ListVector[B]] = 17  fa.foldLeft(empty[B].pure[F])((acc, a) => acc.map2(f(a))(_ + _)) 18  19  override def foldLeft[A, B](fa: ListVector[A], b: B)(f: (B, A) => B): B = 20  fa.foldLeft(b)(f) 21  22  /** 23  * Lazy right fold. Using [[cats.Eval]] is enforced by the typeclass, but it allows us to short-circuit some 24  * folds if necessary. 25  */ 26  override def foldRight[A, B](fa: ListVector[A], init: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = fa match { 27  case h :: t => f(h, Eval.defer(foldRight(t, init)(f))) 28  case _ => init 29  } 30  } 31  32  /** 33  * ListVector forms a monoid for all A types. It's more useful to have a Monoid instance 34  * available than a MonoidK given the functionality is the same for both instances. 35  */ 36  implicit def ListVectorMonoid[A]: Monoid[ListVector[A]] = new Monoid[ListVector[A]] { 37  override def empty: ListVector[A] = ListVector.empty[A] 38  39  override def combine(as0: ListVector[A], as1: ListVector[A]): ListVector[A] = 40  as0 concat as1 41  } 42  43  implicit object ListVectorApplicative extends Applicative[ListVector] { 44  override def pure[A](x: A): ListVector[A] = ListVector(x) 45  46  override def ap[A, B](ff: ListVector[A => B])(fa: ListVector[A]): ListVector[B] = 47  ff foldMap (fa map _) 48  } 49  50  implicit def ListVectorShow[A: Show]: Show[ListVector[A]] = { as => 51  s"ListVector(${as.map(_.show).intercalate(", ")})" 52  } 53  54  implicit def ListVectorHash[A: Hash]: Hash[ListVector[A]] = new Hash[ListVector[A]] { 55  override def hash(x: ListVector[A]): Int = x.hashCode 56  57  override def eqv(x: ListVector[A], y: ListVector[A]): Boolean = ListVectorEq[A].eqv(x, y) 58  } 59  60  /** 61  * Strict equality for two list vectors. The implementation is O(n) as we 62  * go through each of the list elements and compare them. 63  * 64  * @note Could be implemented with foldRight 65  */ 66  implicit def ListVectorEq[A: Eq]: Eq[ListVector[A]] = { (as, bs) => 67  @annotation.tailrec 68  def iter(as: ListVector[A], bs: ListVector[A]): Boolean = 69  if (as.isEmpty && bs.isEmpty) true else as.head === bs.head && iter(as.tail, bs.tail) 70  71  // If the sizes are the same and the hash codes are the same then check individual elements 72  as.size == bs.size && as.hashCode == bs.hashCode && iter(as, bs) 73  } 74  75  implicit def toSeq[A](as: ListVector[A]): Seq[A] = as.toSeq 76 }