Skip to content

Instantly share code, notes, and snippets.

@Sciss
Created June 10, 2017 20:18
Show Gist options
  • Save Sciss/c2585eed77fca8c3a0bfbd1d54c41258 to your computer and use it in GitHub Desktop.
Save Sciss/c2585eed77fca8c3a0bfbd1d54c41258 to your computer and use it in GitHub Desktop.
// cf. http://www.artima.com/scalazine/articles/stackable_trait_pattern.html
trait Request {
type Response
}
trait Context {
def handle[R](req: Request { type Response = R }): R
}
object Foo extends Request {
case class Response(i: Int)
}
object Bar extends Request {
case class Response(s: String)
}
trait HandlesFoo extends Context {
abstract override def handle[R](req: Request { type Response = R }): R =
req match {
case Foo => Foo.Response(123)
case _ => super.handle(req)
}
}
trait HandlesBar extends Context {
abstract override def handle[R](req: Request { type Response = R }): R =
req match {
case Bar => Bar.Response("456")
case _ => super.handle(req)
}
}
// not possible:
// object Attempt1 extends HandlesFoo
trait FinallyFails extends Context {
def handle[R](req: Request { type Response = R }): R =
sys.error(s"Unsupported request $req")
}
object Attempt2 extends FinallyFails with HandlesFoo with HandlesBar
object Baz extends Request {
type Response = Unit
}
import scala.util.Try
Try(Attempt2.handle(Baz))
Attempt2.handle(Foo)
Attempt2.handle(Bar)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment