Type class for Option[T] - type erasure issue?

This code works - I can parse an empty string into Option[Int] as None:

    trait Field[T]:
      def parse(s:String):T

    object Field: 
      given Field[Int] with
	def parse(s:String) = s.toInt

      given Field[Boolean] with
	def parse(s:String) = s.toBoolean

      given Field[Double] with
	def parse(s:String) = s.toDouble

      given Field[Option[Int]] with
	def parse(s:String):Option[Int] = if s.length > 0 then Some(s.toInt) else None

    /* CANNOT DO THIS!

      given Field[Option[Double]] with
	def parse(s:String):Option[Double] = if s.length > 0 then Some(s.toDouble) else None
     ,*/ 

    def fromString[T: Field](s:String):T =
      summon[Field[T]].parse(s)

    val args = Seq("123", "true", "7.5", "", "")

    val myInt = fromString[Int](args(0))
    val myBoolean = fromString[Boolean](args(1))
    val myDouble = fromString[Double](args(2))
    val myOptionInt = fromString[Option[Int]](args(3))
    /* CANNOT DO THIS!

    val myOptionDouble = fromString[Option[Double]](args(4))
     */

    println(myInt)
    println(myBoolean)
    println(myDouble)
    println(myOptionInt)
    /* CANNOT DO THIS!

    println(myOptionDouble)
     */

But I cannot extend idea to Option[Double] because type erasure disallows compiler to recognize both Int and Double in Option[T] - type erasure means at runtime Option[Int] and Option[Double] cannot be distinguished (I think)?

given Field[Option[Double]] with
^
given_Field_Option is already defined as object given_Field_Option
    def parse(s:String):Option[Double] = if s.length > 0 then Some(s.toDouble) else None
Compilation failed

How to get around this in Scala 3 and have type class work with both Option[Int] and Option[Double]?

Similar question was asked recently
The workaround seems to be giving names to your givens.

1 Like