agile-jordi
10/27/2016 - 9:02 PM

ChooseYourOwnStyleService.scala

package com.agilogy.talks.errorhandling.extra

import com.agilogy.talks.errorhandling.Email

import scala.language.higherKinds
import scala.util.{Failure, Success, Try}

case class IllegalEmail(email:String) extends Exception

sealed trait ErrorHandlingStyle{
  type Result[+E<:Exception,+R]
  def failure[E<:Exception,R](error:E):Result[E,R]
  def success[E<:Exception,R](value:R):Result[E,R]
}
object ExceptionsStyle extends ErrorHandlingStyle{
  override type Result[+E<:Exception,+R] = R
  override def failure[E<:Exception,R](error:E):Result[E,R] = {throw error}
  override def success[E<:Exception,R](value:R):Result[E,R] = value
}
object TryStyle extends ErrorHandlingStyle{
  override type Result[+E<:Exception,+R] = Try[R]
  override def failure[E<:Exception,R](error:E):Result[E,R] = Failure(error)
  override def success[E<:Exception,R](value:R):Result[E,R] = Success(value)
}
object EitherStyle extends ErrorHandlingStyle{
  override type Result[+E<:Exception,+R] = Either[E,R]
  override def failure[E<:Exception,R](error:E):Result[E,R] = Left(error)
  override def success[E<:Exception,R](value:R):Result[E,R] = Right(value)
}

case class ChooseYourOwnStyleService[ES<:ErrorHandlingStyle](errorHandling:ES) {
  import errorHandling.{Result, failure,success}

  def parseEmail(email:String):Result[IllegalEmail,Email] = {
    if(email == "foo@example.com") success(Email("foo","example.com"))
    else failure(IllegalEmail(email))
  }

}