Search code examples
scalaimplicit-conversionimplicit

Rounding through type ascription


I would like to introduce a custom class, say Decimal2, so that I would be able to round through type ascription:

val x: Decimal2 = 1.2345
// 1.24

So far I've tried this:

class Decimal2(val value: Double)

object Decimal2 {

  def apply(value: Double) =
    BigDecimal(value).
    setScale(2, BigDecimal.RoundingMode.HALF_UP).
    toDouble

  implicit def doubleToDecimal2(x: Double) = Decimal2(x)

}

val a: Decimal2 = 1.2345

But:

  1. the last line apparently fails.
  2. return type of apply method is Double, not Decimal2

How can I reach my goal?


Solution

  • One way is by explicitly creating a new instance of Decimal2 from apply method.

    object Decimal2 {
      def apply(value: Double): Decimal2 =
        new Decimal2(BigDecimal(value)
          .setScale(2, BigDecimal.RoundingMode.HALF_UP)
          .toDouble)
    
      implicit def doubleToDecimal2(x: Double): Decimal2 = Decimal2(x)
    }
    

    Another option is to tag the type:

    trait RoundTo2
    type Decimal2 = Double with RoundTo2
    
    object Decimal2 {
      def apply(value: Double): Decimal2 = {
        BigDecimal(value)
          .setScale(2, BigDecimal.RoundingMode.HALF_UP)
          .toDouble
      }.asInstanceOf[Double with RoundTo2]
    }
    implicit def doubleToDecimal2(x: Double): Decimal2 = Decimal2(x)
    
    val a: Decimal2 = 1.2345