Skip to content

Instantly share code, notes, and snippets.

@channingwalton
Last active March 24, 2018 16:48
Show Gist options
  • Save channingwalton/0e0f7c73742ddcfaed294f9c92a1a7e8 to your computer and use it in GitHub Desktop.
Save channingwalton/0e0f7c73742ddcfaed294f9c92a1a7e8 to your computer and use it in GitHub Desktop.
NonEmptySet Implementation
import cats.data.NonEmptyList
import cats.Eq
import scala.collection.GenTraversableOnce
sealed trait NonEmptySet[T] extends (T => Boolean) {
def head: T
def set: Set[T]
def +(t: T): NonEmptySet[T]
def ++(ts: NonEmptySet[T]): NonEmptySet[T]
def ++(ts: GenTraversableOnce[T]): NonEmptySet[T]
def -(t: T): Option[NonEmptySet[T]]
def map[U](f: T ⇒ U): NonEmptySet[U]
def apply(t: T): Boolean = set(t)
def contains(t: T): Boolean = set.contains(t)
def size: Int = set.size
def foreach[U](f: T ⇒ U): Unit = set.foreach(f)
def forall(p: T ⇒ Boolean): Boolean = set.forall(p)
def exists(f: T ⇒ Boolean): Boolean = set.exists(f)
def find(f: T ⇒ Boolean): Option[T] = set.find(f)
def collect[U](pf: PartialFunction[T, U]): Option[NonEmptySet[U]] =
NonEmptySet.fromSet(set.collect(pf))
def filter(p: T ⇒ Boolean): Option[NonEmptySet[T]] = NonEmptySet.fromSet(set.filter(p))
def filterNot(p: T ⇒ Boolean): Option[NonEmptySet[T]] = filter(t => !p(t))
def toNonEmptyList: NonEmptyList[T]
override def toString: String = set.toString
}
object NonEmptySet {
private case class NonEmptySet0[T](set: Set[T]) extends NonEmptySet[T] {
def +(t: T): NonEmptySet[T] = NonEmptySet0(set + t)
def ++(ts: NonEmptySet[T]): NonEmptySet[T] = NonEmptySet0(set ++ ts.set)
def ++(ts: GenTraversableOnce[T]): NonEmptySet[T] = NonEmptySet0(set ++ ts)
def -(t: T): Option[NonEmptySet[T]] = fromSet(set - t)
def map[U](f: T ⇒ U): NonEmptySet[U] = NonEmptySet0(set.map(f))
def toNonEmptyList: NonEmptyList[T] = NonEmptyList.fromListUnsafe(set.toList)
@SuppressWarnings(Array("org.wartremover.warts.TraversableOps"))
override def head: T = set.head
}
def fromSet[T](ts: Set[T]): Option[NonEmptySet[T]] =
if (ts.nonEmpty) Option(NonEmptySet0(ts)) else None
def of[T](t: T, ts: T*): NonEmptySet[T] = NonEmptySet0(ts.toSet + t)
def apply[T](ts: T*): Option[NonEmptySet[T]] = fromSet(ts.toSet)
def fromNel[T](ts: NonEmptyList[T]): NonEmptySet[T] = NonEmptySet0(ts.toList.toSet)
implicit class CreationSyntax[T](ts: GenTraversableOnce[T]) {
def toNonEmptySet: Option[NonEmptySet[T]] = apply(ts.toList: _*)
}
implicit def equal[T]: Eq[NonEmptySet[T]] = (x: NonEmptySet[T], y: NonEmptySet[T]) => x == y
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment