Updated Proposal: Revisiting Implicits

I have a beef with implicit conversions. These are bad as everyone knows. I have a library (not yet released, unfortunately) which provides for principled, safe, type-conversions. There are a ton of missing details, but the gist of it is the following:

trait Convert[-A, +B] {
  def apply(x: A): B
}
implicit class AsMethod[A](val self: A) {
  def as[B](implicit c: Convert[A, B]): B = c(self)
}

(please excuse my scala 2 syntax, I’m not familiar enough with dotty yet).

There is a typeclass Convert[A,B] which can be used for converting expressions of type A to something of type B, but the conversion must be done explicitly with the as extension method:

val x: Int = "1729".as[Int]

I find it extremely useful, safe, and not overly onerous to write code this way.

I would like for Convert[A,B] to extend Function[A,B] (because it is clearly a function from A to B) but if I were to do this in Scala 2, every implicit instance of Convert[A,B] would become a candidate for an implicit conversion, which is exactly what I want to avoid.

At first blush, it would seem that the Conversion[A, B] class in the above proposal provides what I want, but it doesn’t, since a given instance of this class allows for implicit conversions (which are bad). However, I don’t just want to use Function[A, B] as my typeclass, because I don’t want every given instance of a function to act as a conversion (Imagine that I had a given instance of type List[String] in scope. Do I really want that to provide an (explicit) conversion from Int to String? No, of course not.)

So what I need is a typeclass that sits in between Function[A,B] and Conversion[A,B] which can be used for explicit conversions (via the as extension method) but not for implicit conversions. If I had my way, this class would be called Conversion[A,B] and the implicit version in the current proposal would be called ImplicitConversion[A,B] (or, better still, UnsafeConversion[A,B]). Implementors would be strongly encourage to provide many instances of Conversion[A,B], but not the dangerous implicit variety.

Of course, in my library the as extension method must be explicitly imported. If it were up to me, I would make this available in the Predef as an extension method available on every type. I would then banish implicit conversions to the dustbin of history.

2 Likes