1

I'm trying to discover the differences between using a value class or a case class in a given scenario. Suppose I want to model the integers mod 5 as a unique datatype. The question is which one I should begin with...

class IntegerMod5(val value: Int) extends AnyVal
case class IntegerMod5(value: Int)

Regardless, it seems that I can create an implementation of Numeric fairly easily. With the case class approach, then, I can simply do this:

case class IntegerMod5(value: Int)(implicit ev: Numeric[IntegerMod5]) {
    import ev.mkNumericOps
}

However, it seems to be a much more difficult endeavour with value classes, mainly as the benefit is to avoid object creation. Thus, something like

implicit class IntegersMod5Ops(value: IntegerMod5)(implicit ev: Numeric[IntegerMod5]) {
    import ev.mkNumericOps
}

Would appear to largely defeat the purpose. (Not sure if it even works, actually.)

The question is that is it possible to use Numeric with a value class, or will I have to bite the bullet and use a case class?

Kelvin Chung
  • 1,327
  • 1
  • 11
  • 23

1 Answers1

1

You don't need implicit ev: Numeric[IntegerMod5] as an argument, just define it in the companion object:

object IntegerMod5 {
  implicit val numeric: Numeric[IntegerMod5] = ...
}

It will be automatically picked up when you use arithmetic operations on IntegerMod5s, and because it's a val, it's only initialized once (you can use object as well).

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487