Skip to content

Commit

Permalink
Merge pull request #3432 from pk044/groupByNelA
Browse files Browse the repository at this point in the history
NonEmptyList.groupByNelA
  • Loading branch information
djspiewak authored Jun 7, 2020
2 parents 07b2b10 + 4a67159 commit 3c44fcd
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
27 changes: 26 additions & 1 deletion core/src/main/scala/cats/syntax/list.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cats
package syntax

import cats.data.{NonEmptyChain, NonEmptyList}

import scala.collection.immutable.SortedMap

trait ListSyntax {
Expand Down Expand Up @@ -52,6 +51,32 @@ final class ListOps[A](private val la: List[A]) extends AnyVal {
toNel.fold(SortedMap.empty[B, NonEmptyList[A]])(_.groupBy(f))
}

/**
* Groups elements inside this `List` according to the `Order` of the keys
* produced by the given mapping monadic function.
*
* {{{
* scala> import cats.data.NonEmptyList
* scala> import scala.collection.immutable.SortedMap
* scala> import cats.implicits._
*
* scala> val list = List(12, -2, 3, -5)
*
* scala> val expectedResult = Option(SortedMap(false -> NonEmptyList.of(-2, -5), true -> NonEmptyList.of(12, 3)))
*
* scala> list.groupByNelA(num => Option(0).map(num >= _)) === expectedResult
* res0: Boolean = true
* }}}
*/
def groupByNelA[F[_], B](f: A => F[B])(implicit F: Applicative[F], B: Order[B]): F[SortedMap[B, NonEmptyList[A]]] = {
implicit val ordering: Ordering[B] = B.toOrdering
val functor = Functor[SortedMap[B, *]]

toNel.fold(F.pure(SortedMap.empty[B, NonEmptyList[A]]))(nel =>
F.map(nel.traverse(a => F.tupleLeft(f(a), a)))(list => functor.map(list.groupBy(_._2))(_.map(_._1)))
)
}

/** Produces a `NonEmptyList` containing cumulative results of applying the
* operator going left to right.
*
Expand Down
6 changes: 6 additions & 0 deletions tests/src/test/scala/cats/tests/ListSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ class ListSuite extends CatsSuite {
}
)

test("groupByNelA should be consistent with groupByNel")(
forAll { (fa: List[Int], f: Int => Int) =>
fa.groupByNelA(f.andThen(Option(_))) should ===(Option(fa.groupByNel(f)))
}
)

test("show") {
List(1, 2, 3).show should ===("List(1, 2, 3)")
(Nil: List[Int]).show should ===("List()")
Expand Down

0 comments on commit 3c44fcd

Please sign in to comment.