@@ -960,6 +960,47 @@ 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+ def splitWhen [A ](fa : F [A ])(f : A => Boolean ): List [List [A ]] = {
979+ toList(fa).reverse.foldLeft(List .empty[A ] :: Nil ) { case (lst, e) =>
980+ if (f(e)) Nil :: lst.head :: lst.tail else (e :: lst.head) :: lst.tail
981+ }
982+ }
983+
984+ /**
985+ * Split this Foldable into a List of Lists based on the effectufl predicate. Monadic version of `splitWhen`
986+ *
987+ * {{{
988+ * scala> import cats.syntax.all._, cats.Foldable, cats.Eval
989+ * scala> Foldable[List].splitWhenM(List(1,1))(x => Eval.now(x == 1)).value
990+ * res1: List[List[Int]] = List(List(), List(), List())
991+ * scala> Foldable[List].splitWhenM(List.empty[Int])(x => Eval.now(x == 1)).value
992+ * res2: List[List[Int]] = List(List())
993+ * scala> Foldable[List].splitWhenM(List(1, 2, 3, 1, 4, 5))(x => Eval.now(x == 1)).value
994+ * val res3: List[List[Int]] = List(List(), List(2, 3), List(4, 5))
995+ * }}}
996+ */
997+ def splitWhenM [G [_], A ](fa : F [A ])(f : A => G [Boolean ])(implicit M : Monad [G ]): G [List [List [A ]]] = {
998+ toList(fa).reverse.foldLeft(M .pure(List .empty[A ] :: Nil )) { case (acc, e) =>
999+ M .flatMap(acc) { case lst =>
1000+ M .map(f(e))(if (_) Nil :: lst.head :: lst.tail else (e :: lst.head) :: lst.tail)
1001+ }
1002+ }
1003+ }
9631004}
9641005
9651006object Foldable {
0 commit comments