Vadim
Vadim

Reputation: 557

General-purpose method that returns a union type

I have a union type Int and String from Union type Scala and I want to add it to general-purpose method. Could u help me to write this method, without compile error.

object OrTypeMain extends App {

  class StringOrInt[T]
  object StringOrInt {
    implicit object IntWitness    extends StringOrInt[Int]
    implicit object StringWitness extends StringOrInt[String]
  }

  object Bar {
    def foo[T: StringOrInt](x: T): Unit = x match {
      case _: String => println("str")
      case _: Int => println("int")
    }

    // target method
    def reverse[T: StringOrInt](x: T): StringOrInt = x match { // not compile
    def reverse[T: StringOrInt](x: T): T = x match { // not compile too

      case x: String => x + "new"
      case y: Int => y + 5
    }
  }

  Bar.reverse(123)
  Bar.reverse("sad")
}

Upvotes: 0

Views: 110

Answers (1)

Dmytro Mitin
Dmytro Mitin

Reputation: 51723

Why reverse doesn't compile is explained here:

Why can't I return a concrete subtype of A if a generic subtype of A is declared as return parameter?

Type mismatch on abstract type used in pattern matching

Replace runtime pattern matching with compile-time type class. StringOrInt is already a type class. Just move your operations there.

trait StringOrInt[T] {
  def reverse(t: T): T
}    
object StringOrInt {
  implicit object IntWitness extends StringOrInt[Int] {
    override def reverse(t: Int): Int = t + 5
  }

  implicit object StringWitness extends StringOrInt[String] {
    override def reverse(t: String): String = t + "new"
  }  
}

def reverse[T: StringOrInt](x: T): T = implicitly[StringOrInt[T]].reverse(x)

Upvotes: 1

Related Questions