10
votes

I recently discovered that one can use the Pimp Enrich My Library pattern to add methods to companion objects using .type:

object Whatever { }

implicit class WhateverExtensions(val obj: Whatever.type) {
    def greet = println("Hi!")
}

Whatever.greet

Unfortunately the same doesn't seem to work for package objects like scala.math:

implicit class MathExtensions(val obj: scala.math.type) {
    def min(x: Money, y: Money): Money = ???
}

I get the following compiler error:

Error:(153, 47) type mismatch;
 found   : math.type
 required: AnyRef
Note that math extends Any, not AnyRef.
Such types can participate in value classes, but instances
cannot appear in singleton types or in reference comparisons.
    implicit class MathExtensions(val obj: scala.math.type) extends AnyVal {
                                                 ^

Is it possible to enrich a package object?

1

1 Answers

9
votes

I don't think it's possible in that fashion, though the documentation is extremely thin. The compiler is clearly treating it differently than a singleton. Even if that method compiled, import scala.math._ would certainly not import your min method, as there is nothing to trigger the implicit conversion. And well, if math.customMin was possible, that would require two imports.

It is possible in another way. We can define anything we want in the scala.math package. We can't define methods at the top-level, though, so we need to employ some object trickery to make it work.

package scala.math

object intMin extends ((Int, Int) => Int) {
    def apply(x: Int, y: Int): Int = x + y
}

Some test:

import scala.math._

object Test extends App {

    println(intMin(4, 10))

}