cats-effect
cats-effect copied to clipboard
UUIDGen Implicit Prioritization Issue on Scala 2.12
trafficstars
Given this code (written this way to make it work with scala-cli repl, which doesn't support kind-projector):
//> using scala 2.12.20
//> using dep org.typelevel::cats-effect:3.6.1
import cats.effect._, cats.effect.std._, cats.data._
import java.util.UUID
import scala.language.higherKinds
type KIOS[a] = Kleisli[IO, String, a]
def foo[F[_]: UUIDGen]: F[UUID] = UUIDGen[F].randomUUID
SecureRandom.javaSecuritySecureRandom[IO].flatMap { implicit random =>
foo[KIOS].run("hello world")
}
the compiler prints
error: ambiguous implicit values:
both method catsKleisliUUIDGen in object UUIDGen of type [F[_], R](implicit evidence$4: cats.effect.std.UUIDGen[F])cats.effect.std.UUIDGen[[γ$1$]cats.data.Kleisli[F,R,γ$1$]]
and method fromSecureRandom in object UUIDGen of type [F[_]](implicit evidence$17: cats.Functor[F], implicit evidence$18: cats.effect.std.SecureRandom[F])cats.effect.std.UUIDGen[F]
match expected type cats.effect.std.UUIDGen[KIOS]
foo[KIOS].run("hello world")
^
The repro code above compiled with CE 3.5.7.
I think the same applies to all the transformers that have instances defined on SecureRandom, so EitherT, Kleisli, OptionT, IndexedStateT, WriterT, IorT, and IndexedReaderWriterStateT.
I think the implicit paths follow these patterns on 2.12:
SecureRandom[F]→UUIDGen.fromSecureRandom[F]→UUIDGen.catsKleisliUUIDGen[F]SecureRandom[F]→SecureRandom.catsKleisliSecureRandom[F]→UUIDGen.fromSecureRandom[Kleisli[…
Updating the example to use
SecureRandom.javaSecuritySecureRandom[IO].flatMap { implicit random =>
IO(reflect.runtime.universe.reify(foo[KIOS].run("hello world")).tree)
}.unsafeRunSync()
gives
foo[KIOS](UUIDGen.catsKleisliUUIDGen(UUIDGen.fromSecureRandom(IO.asyncForIO, random))).run.apply("hello world")
on 2.13 (which is the first path I mentioned above).