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 dec开发者_开发技巧laring
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!)
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)
You can find some examples for this in the lift framework (spec).
import net.liftweb.utils.TimeHelpers._
3.minutes == 6 * 30.seconds
(Note: it seems you need to have reasonable numbers for correct comparison. Eg. There may be no more than 60 seconds.)
You might try scala-time, which is a wrapper around Joda Time and makes it a bit more idiomatic for Scala, including some DSL to do time period computations, similar to what Brian Agnew suggested in his answer.
For instance,
2.hours + 45.minutes + 10.seconds
creates a Joda Period
.
It seems to me a DSL would be of use here. So you could write
2.hours - 5.minutes
and the appropriate conversions would take place to convert 2 hours into a Hours object (value 2) etc.
Lots of resources exist describing Scala's DSL capabilities. e.g. see this from O'Reilly
精彩评论