Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous implicit solution other than sub typing

If you run the code below you'll get an ambiguous implicit error:

class Foo[T,I](val msg: I)
object Foo {
  implicit def provide[T]: Foo[T,String] =
    new Foo("I came from a place you can't touch so subtyping can't help you")
}

class User
object User {
  implicit object userFoo extends Foo[User,Int](42)
}

def fooOf[T,I](U: T)(implicit foo: Foo[T,I]): Foo[T, I] = foo

fooOf(new User).msg //epic fail:
//Error:(232, 7) ambiguous implicit values:
//both object userFoo in object User of type A$A153.this.User.userFoo.type
//and method provide in object Foo of type [T]=> A$A153.this.Foo[T,String]
//match expected type A$A153.this.Foo[A$A153.this.User,I]
//fooOf(new User).msg;//
//^

Normally Scala puts the companion object of type Tin F[T,I] in priority over F[_]'s. But not in this case since the type I in both defined places differ.(if they were both String, Scala would pick the Foo[User,String] in the User Companion object)

I can't (or better say don't want to) touch the Foo companion object to implement LowerPriorityImplicits subtyping technic and define F[User,I] instances inside it on higher priority level. what else can I do?

like image 909
shayan Avatar asked Dec 04 '25 18:12

shayan


1 Answers

I found a solution that allows for function fooOf to explicitly look in companion object only:

sealed trait ILevel
case object FooLevel extends ILevel
case object CompanionLevel extends ILevel

abstract class Foo[T,I](val msg: I) {
  type Level <: ILevel
}
object Foo {
  implicit def provide[T]: Foo[T,String] =
    new Foo[T,String]("I came from a place you can't touch so subtyping can't help you") {
      override type Level = FooLevel.type
    }
}

class User
object User {
  implicit object userFoo extends Foo[User,Int](42) {
    type Level = CompanionLevel.type
  }
}

type CompanionLevelFoo[T,I] = Foo[T,I] {type Level = CompanionLevel.type }

def fooOf[T,I](U: T)(implicit tc2: CompanionLevelFoo[T,I]): Foo[T, I] = tc2

fooOf(new User).msg 

I posted as soon as I found it. Don't know how much trouble it introduces for the gain.

like image 192
shayan Avatar answered Dec 07 '25 15:12

shayan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!