1

Is it possible to pattern match functions in scala ? Specially the return type of the function.

Here is an example. I'm trying to print Shoe if the function's return type is Shoe or Bag otherwise.

object Test extends App {

  trait ProductItem {
    val name: String
    val price: Int
  }

  case class Product(partialPerson: (String) => ProductItem)
  case class Shoe(name: String)(val price: Int) extends ProductItem
  case class Bag(name: String)(val price: Int) extends ProductItem

  val shoe = Shoe("nike")(_)
  val bag = Bag("addidas")(_)

  def printType(shoe: (Int) => ProductItem): Unit = {
    shoe match {
      case isShoe: ((Int) => Shoe) =>
        println("Is a shoe")
      case isBag: ((Int) => Bag) =>
        println("Is a bag")
    }
  }

  printType(shoe)
  printType(bag)
}

Output:
Is a shoe
Is a shoe

Expected output:
Is a shoe
Is a bag

2 Answers 2

5

This is caused by the type erasure in compile time:

<console>:17: warning: non-variable type argument Bag in type pattern Int => Bag is unchecked since it is eliminated by erasure

You can solve it by using TypeTags:

def printType[T](shoe: (Int) => T)(implicit tag: TypeTag[T]): Unit = {
    shoe match {
      case isShoe if tag.tpe =:= typeOf[Shoe]=>
        println("Is a shoe")
      case isBag if tag.tpe =:= typeOf[Bag] =>
        println("Is a bag")
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Is there much perf cost to this? Or is it fine to do in a cross-cutting concern method (logging/metrics)
2

When compiling this code you get a compiler warning tha explains the problem -

Warning:(20, 25) non-variable type argument c.n.p.Shoe in type pattern Int => c.n.p.Shoe is unchecked since it is eliminated by erasure case isShoe: (Int => Shoe) => ^

a possible solution around it -

  def printType[T <: ProductItem : ClassTag](item: Int => T): Unit = {
    implicitly[ClassTag[T]] match {
      case ClassTag(s) if s == classOf[Shoe] =>
        println("Is a shoe")
      case ClassTag(b) if b == classOf[Bag] =>
        println("Is a bag")
    }
  }

To understand this solution you'll have to be familiar with implicit parameters & ClassTag type.

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.