This is a set of libraries that contain Scala collections and collection-oriented utilities that I've found useful. It was previously a sub-project of tmccarthy/tmmUtils, but it has reached a level of maturity that justifies splitting it out.
The libraries have been published to Maven central. They can be used by adding the following to your
val tmmCollectionsVersion = "0.0.1" libraryDependencies += "au.id.tmm.tmm-scala-collections" %% "tmm-scala-collections-core" % tmmCollectionsVersion, libraryDependencies += "au.id.tmm.tmm-scala-collections" %% "tmm-scala-collections-circe" % tmmCollectionsVersion, libraryDependencies += "au.id.tmm.tmm-scala-collections" %% "tmm-scala-collections-cats" % tmmCollectionsVersion, libraryDependencies += "au.id.tmm.tmm-scala-collections" %% "tmm-scala-collections-scalacheck" % tmmCollectionsVersion % Test,
The following collections are provided by the
DupelessSeq: A (poorly-named) collection which can be thought of as a sequence without duplicates, and with a constant-time
containscheck. It differs from
ListSet(and other sets that retain insertion order) in that element order is considered for equality.
DupelessSeqthat is guaranteed to be non-empty.
NonEmptySet: A set that is guaranteed to be non-empty. Unlike the
NonEmptySetprovided by Cats, this collection relies on universal equality in the same way as the Scala set. This makes it easier to use, as elements do not require an
Orderinstance, but comes at the cost of strict-lawfulness.
NonEmptyMap: A map that is guaranteed to be non-empty. Again, like
NonEmptySet, this differs from the Cats
NonEmptyMapin that it relies on universal equality rather than requiring an
Orderinstance for keys.
NonEmptyArraySeq: An immutable
ArraySeqthat is guaranteed to be non-empty.
Third-party library integration
The other modules in this project provide integration between the above collections and some popular FP libraries:
tmm-scala-collections-scalacheckprovides integration with ScalaCheck to support property-based testing.
tmm-scala-collections-circeprovides codecs for use with the Circe json library.
tmm-scala-collections-catsprovides extensive lawful and unlawful instances for the collections above.
tmm-scala-collections-core project provides a few useful syntax extensions via the above import. Some highlights are outlined below:
groupBy method provided by the
IterableOps class can be improved by reflecting the non-empty nature of the groups in the type signature. The
safeGroupBy syntax provides this:
import au.id.tmm.collections.NonEmptySet import au.id.tmm.collections.syntax._ import au.id.tmm.collections.cats.instances.all._ import cats.data.NonEmptyList val list = List("apple", "apricot", "banana") val set = Set("apple", "apricot", "banana") // ❌ BAD, return type doesn't indicate that groups cannot be empty val _: Map[Char, List[String]] = list.groupBy(_.head) val _: Map[Char, Set[String]] = set.groupBy(_.head) // ✅ GOOD, return type indicates that groups are non-empty val _: Map[Char, NonEmptyList[String]] = list.safeGroupBy(_.head) val _: Map[Char, NonEmptySet[String]] = set.safeGroupBy(_.head)
orError operations for
orError syntaxes allow for easily extracting elements from
Iterable collections based on the number of elements. I have found this valuable when processing and cleaning data from external sources:
Rightcontaining the element if the collection has exactly one element,
Right(())if the collection is empty,
Right(None)for empty collections,
Right(Some)for those with one element, and
Leftfor two or more elements.