Search code examples
scalaimportimplicit

Make an implicit from a different object accessible when my object is imported


When someone imports my object, I would like some implicit classes from other objects (or packages) to be available to them. Having import in the object does not help, as imports are not imported transitively, therefore I assume I must use some implicit def or val, however I am unable to find some reasonable way how to achieve this, only a quite verbose def:

object Main extends App {

  object A {

    implicit class ExtendedMath(val x: Double) extends AnyVal {
      def square = x * x
    }

  }

  object X {

    import A._

    // what to write here, so that ExtendedMath is forwarded to our users?
    // following works, but it seems quite verbose
    implicit def extendedMath(x: Double): ExtendedMath = ExtendedMath(x)
  }


  import X._
  val a = 0.0
  println(a.square)
}

Is there some more concise way?


Solution

  • As @stew suggests, the typical approach is to define the implicits in a trait that you can then mix in multiple times. The only caveat is that value classes are not allowed inside a trait, so you have to resort to separating value class and implicit conversion:

    class ExtendedMath(val x: Double) extends AnyVal {
      def square = x * x
    }
    
    trait HasMath {
      // note: method name somehow must not shadow
      // value class name, therefore we use lower-case
      implicit def extendedMath(x: Double): ExtendedMath = new ExtendedMath(x)
    }
    
    object A extends HasMath
    
    object X extends HasMath
    
    object Test {
      import X._
      4.0.square
    }