@@ -960,6 +960,49 @@ trait Foldable[F[_]] extends UnorderedFoldable[F] with FoldableNFunctions[F] { s
960960 import cats .instances .either .*
961961 partitionBifoldM[G , Either , A , B , C ](fa)(f)(A , M , Bifoldable [Either ])
962962 }
963+
964+ /**
965+ * Split this Foldable into a List of Lists based on a predicate.
966+ * The behaviour is aimed to be identical to that of haskell's `splitWhen`
967+ *
968+ * {{{
969+ * scala> import cats.syntax.all._, cats.Foldable
970+ * scala> Foldable[List].splitWhen(List(1,1))(_ == 1)
971+ * res1: List[List[Int]] = List(List(), List(), List())
972+ * scala> Foldable[List].splitWhen(Nil)(_ == 1)
973+ * res2: List[List[Nothing]] = List(List())
974+ * scala> Foldable[List].splitWhen(List(1, 2, 3, 1, 4, 5))(_ == 1)
975+ * res3: List[List[Int]] = List(List(), List(2, 3), List(4, 5))
976+ * }}}
977+ */
978+
979+ def splitWhen [A ](fa : F [A ])(f : A => Boolean ): List [List [A ]] = {
980+ toList(fa).reverse.foldLeft(List .empty[A ] :: Nil ) { case (lst, e) =>
981+ if (f(e)) Nil :: lst else (e :: lst.head) :: lst.tail
982+ }
983+ }
984+
985+ /**
986+ * Split this Foldable into a List of Lists based on the effectufl predicate. Monadic version of `splitWhen`
987+ *
988+ * {{{
989+ * scala> import cats.syntax.all._, cats.Foldable, cats.Eval
990+ * scala> Foldable[List].splitWhenM(List(1,1))(x => Eval.now(x == 1)).value
991+ * res1: List[List[Int]] = List(List(), List(), List())
992+ * scala> Foldable[List].splitWhenM(List.empty[Int])(x => Eval.now(x == 1)).value
993+ * res2: List[List[Int]] = List(List())
994+ * scala> Foldable[List].splitWhenM(List(1, 2, 3, 1, 4, 5))(x => Eval.now(x == 1)).value
995+ * val res3: List[List[Int]] = List(List(), List(2, 3), List(4, 5))
996+ * }}}
997+ */
998+
999+ def splitWhenM [G [_], A ](fa : F [A ])(f : A => G [Boolean ])(implicit M : Monad [G ]): G [List [List [A ]]] = {
1000+ toList(fa).reverse.foldLeft(M .pure(List .empty[A ] :: Nil )) { case (acc, e) =>
1001+ M .flatMap(acc) { case lst =>
1002+ M .map(f(e))(if (_) Nil :: lst else (e :: lst.head) :: lst.tail)
1003+ }
1004+ }
1005+ }
9631006}
9641007
9651008object Foldable {
0 commit comments