Case Class and Implicit Arguments and Pattern Matching

Alex's answer is clever, however I don't really like the _ in the object name, I find the syntax a little strange and remembering the underscore makes pattern matching more difficult to use. (Of course this is all subjective so your feelings may vary).

My first approach to dealing with this were to move the implicit parameters to the apply method in the companion object.

case class A(i: Int, b: Boolean)

object Foo {
  def apply(i: Int)(implicit b: Boolean): Foo = apply(a, b)
}

But this results in

Error:(21, 14) double definition: 
method apply:(i: Int, b: Boolean)com.workday.cloud.master.package.A and 
method apply:(i: Int)(implicit b: Boolean)com.workday.cloud.master.package.A at line 24 
have same type after erasure: (i: Int, b: Boolean)com.workday.cloud.master.package.A   
  case class A(i: Int, b: Boolean)
             ^

We can fix this by adding an extra unused implicit parameter.

object A {
  def apply(i: Int)(implicit b: Boolean, unused: DummyImplicit): A = apply(i, b)
}

Which approach you choose is up to you, I find this approach enables my client code to look more natural.


You can define a case class with implicit arguments, but as you've discovered, they're not available for pattern matching. You could always write your own extractor though:

case class C(i: Int)(implicit val b: Boolean)

// You can't call this C because that seat is taken (can't overload the default unapply)
object C_ { 
  // In order to be able to select `b` here, 
  // it needs to be declared as "implicit *val* b: Boolean"
  def unapply(in: C) = Some((in.i, in.b)) 
}

c1 match {
  case C_(i, b) => ...
}

Tags:

Scala