Skip to content

Instantly share code, notes, and snippets.

@wheaties
Forked from anonymous/gist:4484300
Last active December 10, 2015 19:48
Show Gist options
  • Save wheaties/4484330 to your computer and use it in GitHub Desktop.
Save wheaties/4484330 to your computer and use it in GitHub Desktop.
An effect which can be "undone."
trait Change[+A]{
def map[B](f: A => B): Change[B]
def flatMap[B](f: A => Change[B]): Change[B]
def foreach(f: A => Unit): Unit
def filter(pred: A => Boolean): Change[A]
}
case class Reversible[+A](value: A, undo: List[Undo]) extends Change[A]{
def map[B](f: A => B) = Reversible(f(value), undo)
def flatMap[B](f: A => Change[B]) = f(value) match{
case Reversible(x, u) => Reversible(x, u ::: undo)
case Irreversible(x) => Reversible(x, undo)
}
def foreach(f: A => Unit){
f(value)
}
def filter(pred: A => Boolean) = if(pred(value)) this else NeverHappened(new Exception("predicate condition failed", undo)
}
case class Irreversible[+A](value: A) extends Change[A]{
def map[B](f: A => B) = Irreversible(f(value))
def flatMap[B](f: A => Change[B]) = f(value)
def foreach(f: A => Unit){
f(value)
}
def filter(pred: A => Boolean) = if(pred(value)) this else NeverHappened(new Exception("predicate condition failed", Nil)
}
case class NeverHappened[+A](ex: Exception, undo: List[Undo]) extends Change[A]{
def map[B](f: A => B) = NeverHappened[B](ex, undo)
def flatMap[B](f: A => Change[B]) = NeverHappened[B](ex, undo)
def foreach(f: A => Unit){}
def filter(pred: A => Boolean) = this
}
class Undo(f: => Any) extends (() => Unit){
def apply(){ f }
}
//Could it also be done as?
class UndoChange(f: => Any) extends (() => Unit) extends Change[Any]{
def map[B](g: Any => B) = new UndoChange{
def apply(){ g(f) }
}
def flatMap[B](g: Any => Change[B]) = map(g)
def apply(){ f }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment