Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/tmccarthy/tmm-scala-collections
Some collections I find useful
https://github.com/tmccarthy/tmm-scala-collections
Last synced: about 1 month ago
JSON representation
Some collections I find useful
- Host: GitHub
- URL: https://github.com/tmccarthy/tmm-scala-collections
- Owner: tmccarthy
- License: apache-2.0
- Created: 2020-05-30T08:17:33.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2022-07-26T11:02:17.000Z (over 2 years ago)
- Last Synced: 2023-07-31T19:44:12.548Z (over 1 year ago)
- Language: Scala
- Size: 606 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# `tmm-scala-collections`
[![CircleCI](https://circleci.com/gh/tmccarthy/tmm-scala-collections.svg?style=svg)](https://app.circleci.com/pipelines/github/tmccarthy/tmm-scala-collections)
[![Maven Central](https://img.shields.io/maven-central/v/au.id.tmm.tmm-scala-collections/tmm-scala-collections-core_2.13.svg)](https://repo.maven.apache.org/maven2/au/id/tmm/tmm-scala-collections/tmm-scala-collections-core_2.13/)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](https://github.com/tmccarthy/tmmUtils), but it has reached a level of
maturity that justifies splitting it out.## Usage
The libraries have been published to Maven central. They can be used by adding the following to your `build.sbt`
```scala
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,
```## Collections
The following collections are provided by the `tmm-scala-collections-core` artefact:
* [`DupelessSeq`](/core/src/main/scala/au/id/tmm/collections/DupelessSeq.scala): A (poorly-named) collection which can
be thought of as a sequence without duplicates, and with a constant-time `contains` check. It differs from [`ListSet`](https://www.scala-lang.org/api/current/scala/collection/immutable/ListSet.html)
(and other sets that retain insertion order) in that element order is considered for equality.
* [`NonEmptyDupelessSeq`](/core/src/main/scala/au/id/tmm/collections/NonEmptyDupelessSeq.scala): A `DupelessSeq` that is
guaranteed to be non-empty.
* [`NonEmptySet`](/core/src/main/scala/au/id/tmm/collections/NonEmptySet.scala): A set that is guaranteed to be
non-empty. Unlike the [`NonEmptySet`](https://typelevel.org/cats/api/cats/data/NonEmptySetOps.html) provided by [Cats](https://github.com/typelevel/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 `Order` instance, but comes at the cost of strict-lawfulness.
* [`NonEmptyMap`](/core/src/main/scala/au/id/tmm/collections/NonEmptyMap.scala): A map that is guaranteed to be
non-empty. Again, like `NonEmptySet`, this differs from the Cats `NonEmptyMap` in that it relies on universal equality
rather than requiring an `Order` instance for keys.
* [`NonEmptyArraySeq`](/core/src/main/scala/au/id/tmm/collections/NonEmptyArraySeq.scala): An immutable [`ArraySeq`](https://www.scala-lang.org/api/current/scala/collection/immutable/ArraySeq$.html)
that 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-scalacheck` provides integration with [ScalaCheck](https://github.com/typelevel/scalacheck) to
support property-based testing.
* `tmm-scala-collections-circe` provides codecs for use with the [Circe](https://github.com/circe/circe) json library.
* `tmm-scala-collections-cats` provides extensive lawful and unlawful instances for the collections above.## Syntax
```scala
import au.id.tmm.collections.syntax._
```The `tmm-scala-collections-core` project provides a few useful syntax extensions via the above import. Some highlights
are outlined below:#### Safe `groupBy`
The [`groupBy`](https://www.scala-lang.org/api/current/scala/collection/IterableOps.html#groupBy[K](f:A=%3EK):scala.collection.immutable.Map[K,C])
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:```scala
import au.id.tmm.collections.NonEmptySet
import au.id.tmm.collections.syntax._
import au.id.tmm.collections.cats.instances.all._
import cats.data.NonEmptyListval 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 `Iterable`
The `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:* `onlyElementOrException` returns a `Right` containing the element if the collection has exactly one element, `Left`
otherwise.
* `emptyOrException` returns `Right(())` if the collection is empty, `Left` otherwise
* `atMostOne` returns `Right(None)` for empty collections, `Right(Some)` for those with one element, and `Left` for two
or more elements.