Search code examples
scalatypesfunctional-programmingparameterized

Type parameterized arithmetic?


Trying to think of a way to subtract 5 minutes from 2 hours.

It doesn't make sense to subtract 5 from 2, because we end up with -3 generic time units, which is useless. But if "hour" is a subtype of "minute", we could convert 2 hours to 120 minutes, and yield 115 minutes, or 1 hour and 55 minutes.

Similarly, if we want to add 5 apples to 5 oranges, we cannot evaluate this in terms of apples, but might expect to end up with 10 fruit.

It seems in the above examples, and generally when using a number as an adjective, the integers need to be parameterized by the type of object they describing. I think it would be very useful if instead of declaring

val hours = 2
val minutes = 5

you could do something like

val hours = 2[Hour]
val minutes = 5[Minute]
val result = hours - minutes
assert (result == 115[Minute])

Does anything like this exist, would it be useful, and is it something that could be implemented?

EDIT: to clarify, the time example above is just a random example I thought up. My question is more whether in general the idea of parameterized Numerics is a useful concept, just as you have parameterized Lists etc. (The answer might be "no", I don't know!)


Solution

  • You can accomplish this by having two classes for Hours and Minutes, along with an implicit conversion function from hours to minutes

    trait TimeUnit
    case class Hour(val num: Int) extends TimeUnit      
    case class Minute(val num: Int) extends TimeUnit {
      def - (sub: Minute) = Minute(num - sub.num)
    }
    
    implicit def hour2Minute(hour: Hour) = Minute(hour.num * 60)
    

    This allows you to do something like

    val h = Hour(2) - Minute(30) //returns Minute(90)