0

I want to build a function that takes as input a generic function with one argument, than parse the argument based on type and call the input function:

class PatternMatching {
    val a = "test"
    def test[T: TypeTag](callback: T => Unit): Unit = {
    callback match {
      case x if  typeOf[T] <:< typeOf[String] => callback(a)
      case x if  typeOf[T] <:< typeOf[Array[Char]] => callback(a.toCharArray)

      case _ => throw new IllegalArgumentException("error")

    }
  }
} 

I see that type is correctly inferred but is not possible to invoke the function:

type mismatch; found : PatternMatching.this.a.type (with underlying type String) required: T case x if typeOf[T] <:< typeOf[String] => callback(a)

I understand that it's expecting a type, but I can't find a way out.

2 Answers 2

1

You need explicit .asInstanceOf[T] with the method you've written:

callback(a.asInstanceOf[T])

Though, what you're trying to achieve is typically done with typeclass in Scala. I let the reader search about it but the general idea is you would have your method defined like this:

def test[T](callback: T => Unit)(implicit converter: ConverterFromString[T]): Unit = {
  callback(converter.fromString(a))
}      

And there would exist in scope some values of ConverterFromString for only some types you know how to handle.

The huge benefit of this approach is to be type-safe and if will raise errors at compile time rather than runtime if a type cannot be handled.

Sign up to request clarification or add additional context in comments.

Comments

0

Using typeclass as suggested by @Gaël J works:

trait Converter[A] {
  def conveterFromString(a: String): A
}

object Converter {
  implicit val stringConverter: Converter[String] = new Converter[String] {
    def conveterFromString(x: String): String = x
  }
  implicit val arrayConverter: Converter[Array[Char]] = new Converter[Array[Char]] {
    def conveterFromString(x: String): Array[Char] = x.toCharArray
  }
}

class PatternMatching {
  val a = "test"

  def test[A](callback: A => Unit)(implicit converter: Converter[A]): Unit =
    callback(converter.conveterFromString(a))
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.