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.