in Scala 2, they don't chain π, even if we try to give the compiler an assist
can we make them chain in Dotty? π
let's try it!
first let's set up sbt:
% cat project/plugins.sbt
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.3.3")
% cat build.sbt
scalaVersion := crossScalaVersions.value.head
crossScalaVersions := Seq("2.13.0", "0.16.0-RC3")
then let's write some Scala 2 code:
import language.implicitConversions
class A; class B; class C
object O {
implicit def a2b(a: A): B = new B
implicit def b2c(b: B): C = new C
implicit def chain[T1,T2,T3](x: T1)(implicit c1: T1 => T2, c2: T2 => T3): T3 =
c2(c1(x))
// will it compile?
(new A): C
}
and try it in both Scala 2 and Dotty:
sbt:chain-2-13> ;++0.16.0-RC3 ;compile
[info] Setting Scala version to 0.16.0-RC3 on 1 projects.
[info] Reapplying settings...
[info] Set current project to chain-2-13 (in build file:/Users/tisue/tmp/chain-2.13/)
[info] Updating ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/tisue/tmp/chain-2.13/target/scala-0.16/classes ...
[info] Done compiling.
[success] Total time: 0 s, completed Jun 19, 2019 4:26:43 PM
sbt:chain-2-13> ;++2.13.0 ;compile
[info] Setting Scala version to 2.13.0 on 1 projects.
[info] Reapplying settings...
[info] Set current project to chain-2-13 (in build file:/Users/tisue/tmp/chain-2.13/)
[info] Compiling 1 Scala source to /Users/tisue/tmp/chain-2.13/target/scala-2.13/classes ...
[error] /Users/tisue/tmp/chain-2.13/S.scala:11:4: type mismatch;
[error] found : A
[error] required: C
[error] (new A): C
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 0 s, completed Jun 19, 2019 4:26:45 PM
Scala 2 does not allow us to chain conversions in this way π; Dotty does! π
That's using implicit def
. What if we use delegate
?
import language.implicitConversions
class A; class B; class C
object O {
delegate for Conversion[A, B] = _ => new B
delegate for Conversion[B, C] = _ => new C
delegate [T1, T2, T3] for Conversion[T1, T3]
given (c1: Conversion[T1, T2], c2: Conversion[T2, T3]) =
x => c2(c1(x))
the[Conversion[A, C]] // compiles!
// DOES NOT COMPILE:
// (new A): C
}
I don't understand this π€; if delegate search finds an Conversion[A, C]
, then why wouldn't (new A): C
compile?
Note that this gist was written before the naming for givens in Scala 3 had been decided.
delegate
is what eventually becamegiven
, andthe
is nowsummon
. Andgiven
, well, that becameusing
:-)