jimmydivvy
10/10/2014 - 8:12 AM

SemigroupTest.scala

import scalaz._, Scalaz._

sealed trait Action 

case class Insert(ids:Seq[Int]) extends Action
case class Update(ids:Seq[Int]) extends Action
case class Delete(ids:Seq[Int]) extends Action

object Test extends App {

	implicit def InsertSemigroup = new Semigroup[Insert] {
		def append( f1:Insert, f2: => Insert ) = Insert( f1.ids ++ f2.ids )
	}

	implicit def UpdateSemigroup = new Semigroup[Update] {
		def append( f1:Update, f2: => Update ) = Update( f1.ids ++ f2.ids )	
	}

	implicit def DeleteSemigroup = new Semigroup[Delete] {
		def append( f1:Delete, f2: => Delete ) = Delete( f1.ids ++ f2.ids )	
	}

	// implicit class InsertSemigroup extends Semigroup[Insert] {
	// 	def append( f1:Insert, f2:Insert ) = Insert( f1.ids |+| f2.ids )
	// }

	val xs = List(
		Insert(List(1)),
		Insert(List(2)),
		Update(List(1)),
		Insert(List(3)),
		Update(List(4)),
		Delete(List(1))
	)

	def tagName(action:Action) = action match {
		case _:Insert => 'Insert
		case _:Update => 'Update
		case _:Delete => 'Delete 
	}

	
	
	def mergeActions( actions:List[Action] ) = actions.reduceLeft { (acc, x) => (acc, x) match {
		case (acc:Insert, x:Insert) => acc |+| x
		case (acc:Update, x:Update) => acc |+| x
		case (acc:Delete, x:Delete) => acc |+| x
		case _ => throw new RuntimeException("Cannot concat actions of different types")
	}}


	val result = xs.groupBy(tagName).values.map(mergeActions)

	println(result)

}