Skip to content

Instantly share code, notes, and snippets.

@ubourdon
Last active July 30, 2018 09:32
Show Gist options
  • Select an option

  • Save ubourdon/16800b017f4d6b55f8d09cce7e0baa8a to your computer and use it in GitHub Desktop.

Select an option

Save ubourdon/16800b017f4d6b55f8d09cce7e0baa8a to your computer and use it in GitHub Desktop.
Define newtype with smart constructor in scala
import scalaz.{@@, Show, Tag, \/}
import scalaz.Scalaz.ToEitherOps
/**
* Double représentant un pourcentage.
*/
package object percentagedouble {
private[percentagedouble] sealed trait PositiveOrNegativePercentageDoubleTag
type PositiveOrNegativePercentageDouble = Double @@ PositiveOrNegativePercentageDoubleTag
sealed trait PositiveOrNegativePercentageDoubleError
case class InvalidRawValue(error: String) extends PositiveOrNegativePercentageDoubleError
case class OperationError(error: String) extends PositiveOrNegativePercentageDoubleError
/**
* Représente un pourcentage qui peut être positive ou négatif
*/
object PositiveOrNegativePercentageDouble {
def apply(rawValue: Double): InvalidRawValue \/ PositiveOrNegativePercentageDouble = {
if(rawValue >= -1 && rawValue <= 1) buildType(rawValue).right
else InvalidRawValue("must be a -1 <= double <= 1").left
}
/**
* a.k.a unwrap function
*
* @param i
* @return the unwrapped string value
*/
def rawValue(i: PositiveOrNegativePercentageDouble): Double = Tag.unwrap(i)
/**
* Allow to use scalaz Show typeclass
*/
implicit val showPositiveOrNegativePercentageDouble: Show[PositiveOrNegativePercentageDouble] = Show shows { i => s"PositiveOrNegativePercentageDouble(${Tag.unwrap(i)})" }
private def buildType(i: Double) = Tag.apply[Double, PositiveOrNegativePercentageDoubleTag](i)
val MINUS_ONE = buildType(-1)
val ZERO = buildType(0)
val ONE = buildType(1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment