package com.sageserpent.americium

import scala.collection.immutable.List

trait SeqEnrichment {
  implicit class RichSeq[Item](items: Seq[Item]) {
    def groupWhile(predicate: (Item, Item) => Boolean) = {
      if (items.isEmpty)
        Seq.empty[Seq[Item]]
      else {
        val Seq(head, tail @ _ *) = items
        val reversedGroupsInReverse =
          tail.foldLeft(List(List(head)))((groups, item) => {
            assert(groups.nonEmpty)
            groups match {
              case (headGroup @ (itemToMatch :: _)) :: tailGroups
                  if predicate(itemToMatch, item) =>
                (item :: headGroup) :: tailGroups
              case _ => List(item) :: groups
            }
          })
        reversedGroupsInReverse map (_.reverse) reverse
      }
    }
  }
}

package com.sageserpent.americium

import scala.collection.generic.CanBuildFrom
import scala.collection.immutable.List

trait SeqEnrichment {
  implicit class RichSeq[Container[Element] <: Seq[Element] forSome {
    type Element
  }, Item](items: Seq[Item]) {
    def groupWhile(predicate: (Item, Item) => Boolean)(
        implicit cbf: CanBuildFrom[List[Item], Item, Container[Item]])
      : Seq[Container[Item]] = {
      if (items.isEmpty)
        Seq.empty[Container[Item]]
      else {
        val Seq(head, tail @ _ *) = items
        val reversedGroupsInReverse =
          tail.foldLeft(List(List(head)))((groups, item) => {
            assert(groups.nonEmpty)
            groups match {
              case (headGroup @ (itemToMatch :: _)) :: tailGroups
                  if predicate(itemToMatch, item) =>
                (item :: headGroup) :: tailGroups
              case _ => List(item) :: groups
            }
          })
        reversedGroupsInReverse map (_.reverse) map { items =>
          val builder = cbf()
          items.foreach(builder += _)
          builder.result
        } reverse
      }
    }
  }
}

Use a builder to preserve the original collection type in the result of 'groupBy'.
Use a builder to preserve the original collection type in the result of 'groupBy'.