Skip to content

Instantly share code, notes, and snippets.

@rizsotto
Created March 10, 2017 10:35
Show Gist options
  • Save rizsotto/d3f1b83a19765d545f2d1d828f5eb6a7 to your computer and use it in GitHub Desktop.
Save rizsotto/d3f1b83a19765d545f2d1d828f5eb6a7 to your computer and use it in GitHub Desktop.
strange list fold with state monad
import scalaz.State
import scalaz._
import Scalaz._
sealed trait InputMsg{
def id: Int
}
case class Started(id: Int) extends InputMsg
case class Stopped(id: Int) extends InputMsg
sealed trait OutputMsg
case class InProgress(id: Int) extends OutputMsg()
case class Finished(id: Int) extends OutputMsg
object Example {
type Stack = List[InputMsg]
def pop(pivot: InputMsg) = State[Stack, InputMsg] { state: Stack =>
val (pair, rest) = state.partition(_.id == pivot.id)
(rest, pair.head)
}
def push(pivot: InputMsg) = State[Stack, Unit] {
case xs => (pivot :: xs, ())
}
def handler(input: InputMsg): State[Stack, Option[OutputMsg]] =
input match {
case e@Started(id) => for {
_ <- push(e)
} yield None
case e@Stopped(id) => for {
_ <- pop(e)
} yield Some(Finished(id))
}
def smash(input: List[InputMsg]): List[OutputMsg] = {
val initial = List[InputMsg]()
val (started, finished) = input.runTraverseS(initial)(handler)
finished.flatMap {
case Some(x) => List(x)
case None => List()
} ++
started.map {
case Started(id) => InProgress(id)
}
}
def main(args: Array[String]): Unit = {
val input: List[InputMsg] = List(Started(1), Started(2), Stopped(1))
//val expected: List[OutputMsg] = List(Finished(1), InProgress(2))
println(s"input was: $input")
println(s"result is: ${smash(input)}")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment