I did some exercises in Scala. I thought I would try to deduce a method for creating incompatible value types that cannot be accidentally assigned to each other using the recently added AnyVal .
The best I could come up with was something like this:
object Measurements { trait ValueType[T] extends Any { def value: T } trait Measurement[A <: ValueType[Double]] extends Any { def modify(fn: (Double, A) => Double, value: A): A def +(mod: A) = modify((x: Double, y: A) => x + y.value, mod) def -(mod: A) = modify((x: Double, y: A) => x - y.value, mod) def *(mod: A) = modify((x: Double, y: A) => x * y.value, mod) def /(mod: A) = modify((x: Double, y: A) => x / y.value, mod) } case class Frequency(value: Double) extends AnyVal with ValueType[Double] with Measurement[Frequency] { def modify(fn: (Double, Frequency) => Double, mod: Frequency) = Frequency(fn(value, mod)) } case class Amplitude(value: Double) extends AnyVal with ValueType[Double] with Measurement[Amplitude] { def modify(fn: (Double, Amplitude) => Double, mod: Amplitude) = Amplitude(fn(value, mod)) } case class Wavelength(value: Double) extends AnyVal with ValueType[Double] with Measurement[Wavelength] { def modify(fn: (Double, Wavelength) => Double, mod: Wavelength) = Wavelength(fn(value, mod)) } } import Measurements._ Frequency(150) + Frequency(10)
Unfortunately, for each instance, you need to uniquely define a modify function, because it is impossible to define something like A(value) with a common type A There seems to be no way to define constructor constraints. Otherwise, I could define something in common in the dash, for example:
def modify(fn: (Double, A) => Double, mod: A) = A(fn(value, mod))
I tried calling apply(Double) on A , but it is not available from a shared variable. I also tried to understand if I could somehow create a factory in order to at least simplify things, but could not come up with anything more graceful than what I am doing now. I am facing the same issue with C # all the time.
Is there a way to account for this code, which relies on a generic constructor type for different (but related) classes?