Skip to content

Commit 44a9ea1

Browse files
optimize implementations
1 parent adec14b commit 44a9ea1

2 files changed

Lines changed: 20 additions & 6 deletions

File tree

core/src/main/scala/cats/syntax/list.scala

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,26 @@ final class ListOps[A](private val la: List[A]) extends AnyVal {
180180
*/
181181

182182
def splitWhenM[G[_]](f: A => G[Boolean])(implicit M: Monad[G]): G[NonEmptyList[List[A]]] = {
183-
la.reverse.foldLeft(M.pure(NonEmptyList.one(List.empty[A]))) { case (acc, e) =>
184-
M.flatMap(acc) { case lst =>
185-
M.map(f(e))(if (_) Nil :: lst else NonEmptyList(e :: lst.head, lst.tail))
183+
type State = (List[A], NonEmptyList[List[A]])
184+
185+
def step(state: State): G[Either[State, NonEmptyList[List[A]]]] =
186+
state match {
187+
case (e :: rest, acc) =>
188+
M.map(f(e)) { shouldSplit =>
189+
val nextAcc =
190+
if (shouldSplit) Nil :: acc
191+
else NonEmptyList(e :: acc.head, acc.tail)
192+
193+
Left((rest, nextAcc))
194+
}
195+
196+
case (Nil, acc) =>
197+
M.pure(Right(acc))
186198
}
187-
}
199+
200+
M.tailRecM((la.reverse, NonEmptyList.one(List.empty[A])))(step)
188201
}
202+
189203
}
190204

191205
private[syntax] trait ListSyntaxBinCompat0 {

tests/shared/src/test/scala/cats/tests/ListSuite.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ class ListSuite extends CatsSuite {
138138
assert(sumAll == lst.sum)
139139
}
140140

141-
test(s"splitWhen") {
141+
test("splitWhen") {
142142
forAll { (li: List[Int]) =>
143143
val pred = (x: Int) => x > 0
144144
val res = li.splitWhen(pred)
@@ -149,7 +149,7 @@ class ListSuite extends CatsSuite {
149149
}
150150
}
151151

152-
test(s"splitWhenM") {
152+
test("splitWhenM") {
153153
forAll { (li: List[Int]) =>
154154
val pred = (x: Int) => x > 0
155155
val predM = (x: Int) => Eval.now(pred(x))

0 commit comments

Comments
 (0)