All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gem.instances.TreeSetInstances.scala Maven / Gradle / Ivy

The newest version!
// Copyright (c) 2016-2020 Association of Universities for Research in Astronomy, Inc. (AURA)
// For license information see LICENSE or https://opensource.org/licenses/BSD-3-Clause

package gem.instances

import cats._
import cats.kernel.{BoundedSemilattice, Hash, Order}
import scala.collection.immutable.TreeSet
import scala.annotation.tailrec
import cats.implicits._

trait TreeSetInstances extends TreeSetInstances1 {

  implicit val catsStdInstancesForTreeSet: Foldable[TreeSet] with SemigroupK[TreeSet] =
    new Foldable[TreeSet] with SemigroupK[TreeSet] {

      def combineK[A](x: TreeSet[A], y: TreeSet[A]): TreeSet[A] = x | y

      def foldLeft[A, B](fa: TreeSet[A], b: B)(f: (B, A) => B): B =
        fa.foldLeft(b)(f)

      def foldRight[A, B](fa: TreeSet[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
        Foldable.iterateRight(fa, lb)(f)

      override def foldMap[A, B](fa: TreeSet[A])(f: A => B)(implicit B: Monoid[B]): B =
        B.combineAll(fa.iterator.map(f))

      override def get[A](fa: TreeSet[A])(idx: Long): Option[A] = {
        @tailrec
        def go(idx: Int, it: Iterator[A]): Option[A] = {
          if (it.hasNext) {
            if (idx == 0) Some(it.next) else {
              it.next
              go(idx - 1, it)
            }
          } else None
        }
        if (idx < Int.MaxValue && idx >= 0L)  go(idx.toInt, fa.toIterator) else None
      }

      override def size[A](fa: TreeSet[A]): Long = fa.size.toLong

      override def exists[A](fa: TreeSet[A])(p: A => Boolean): Boolean =
        fa.exists(p)

      override def forall[A](fa: TreeSet[A])(p: A => Boolean): Boolean =
        fa.forall(p)

      override def isEmpty[A](fa: TreeSet[A]): Boolean = fa.isEmpty

      override def fold[A](fa: TreeSet[A])(implicit A: Monoid[A]): A = A.combineAll(fa)

      override def toList[A](fa: TreeSet[A]): List[A] = fa.toList

      override def reduceLeftOption[A](fa: TreeSet[A])(f: (A, A) => A): Option[A] =
        fa.reduceLeftOption(f)

      override def find[A](fa: TreeSet[A])(f: A => Boolean): Option[A] = fa.find(f)

      override def collectFirst[A, B](fa: TreeSet[A])(pf: PartialFunction[A, B]): Option[B] =
        fa.collectFirst(pf)

      override def collectFirstSome[A, B](fa: TreeSet[A])(f: A => Option[B]): Option[B] =
        fa.collectFirst(Function.unlift(f))
    }

  implicit def catsStdShowForTreeSet[A: Show]: Show[TreeSet[A]] = new Show[TreeSet[A]] {
    def show(fa: TreeSet[A]): String =
      fa.toIterator.map(_.show).mkString("TreeSet(", ", ", ")")
  }

  implicit def catsKernelStdOrderForTreeSet[A: Order]: Order[TreeSet[A]] =
    new TreeSetOrder[A]
}

trait TreeSetInstances1 {
  implicit def catsKernelStdHashForTreeSet[A: Order: Hash]: Hash[TreeSet[A]] =
    new TreeSetHash[A]

  implicit def catsKernelStdSemilatticeForTreeSet[A: Order]: BoundedSemilattice[TreeSet[A]] =
    new TreeSetSemilattice[A]
}

class TreeSetOrder[A: Order] extends Order[TreeSet[A]] {
  def compare(a1: TreeSet[A], a2: TreeSet[A]): Int = {

    Order[Int].compare(a1.size, a2.size) match {
      case 0 => Order.compare(a1.toStream, a2.toStream)
      case x => x
    }
  }

  override def eqv(s1: TreeSet[A], s2: TreeSet[A]): Boolean = {
    // implicit val x = Order[A].toOrdering
    s1.toStream.corresponds(s2.toStream)(Order[A].eqv)
  }
}

class TreeSetHash[A: Order: Hash] extends Hash[TreeSet[A]] {
  import scala.util.hashing.MurmurHash3._

  // adapted from [[scala.util.hashing.MurmurHash3]],
  // but modified standard `Any#hashCode` to `ev.hash`.
  def hash(xs: TreeSet[A]): Int = {
    var a, b, n = 0
    var c = 1
    xs foreach { x =>
      val h = Hash[A].hash(x)
      a += h
      b ^= h
      if (h != 0) c *= h
      n += 1
    }
    var h = setSeed
    h = mix(h, a)
    h = mix(h, b)
    h = mixLast(h, c)
    finalizeHash(h, n)
  }
  override def eqv(s1: TreeSet[A], s2: TreeSet[A]): Boolean = {
    // implicit val x = Order[A].toOrdering
    s1.toStream.corresponds(s2.toStream)(Order[A].eqv)
  }
}

class TreeSetSemilattice[A: Order] extends BoundedSemilattice[TreeSet[A]] {
  def empty: TreeSet[A] = TreeSet.empty(implicitly[Order[A]].toOrdering)
  def combine(x: TreeSet[A], y: TreeSet[A]): TreeSet[A] = x | y
}

object treeset extends TreeSetInstances




© 2015 - 2024 Weber Informatics LLC | Privacy Policy