In my project, I’m using Scala 3 and I think I’ve found a weird case where an polymorphic extension method is not working well with custom literal types. I’ve reduced down the code so that I can show the issue with a minimum code:
object Demo2:
extension [T](either: Either[String, T])
def toOptionCustom: Option[T] = either.fold(_ => None, Some(_))
type MyValue = "value1" | "value2" | "value3"
val myValues: List[MyValue] = List("value1", "value2", "value3")
def toMyValue(value: String): Either[String, MyValue] = myValues.find(_.toString == value).toRight("Invalid value")
def hello(myValue: MyValue): String = s"Hello $myValue"
def demo1: Option[String] =
toMyValue("value1").toOption.map(hello) // this line compiles
def demo2: Option[String] =
toMyValue("value1").fold(_ => None, Some(_)).map(hello) // this line also compiles
def demo3: Option[String] =
toMyValue("value1").toOptionCustom.map(hello) // but this line doesn't compile
The compiler fails to compile the last line saying that the function hello
should be String => String
type, which is wrong in my opinion. It should accept MyValue => String
type function and hello
conforms to it. toOptionCustom
method is basically my custom implementation of toOption
and I think it should work. demo2
and demo3
is basically identical except that demo3
goes through the extension method. Am I missing something?