It’d be useful to have an intermediate interface that integer number types could implement, like Int, Long and BigInteger. On the dual side, a common interface for floating point number types would also be useful, for Float, Double, BigDecimal, etc.
This would allow the compiler to make my life easier when I need an arbitrary length for a number, but I want a specific category.
Now I’m forced to overload some declarations, like
val Int.pennies: Pounds get() = Pounds(this.toBigInteger())
val Long.pennies: Pounds get() = Pounds(this.toBigInteger())
val BigInteger.pennies: Pounds get() = Pounds(pennies = this)
and it’d be great to be able to write instead
val IntegerNumber.pennies: Pounds = Pounds(this)
There are many more use cases for both integer number and floating point numbers.
1 Like
Probably you are talking about the shape classes.
Theoretically, they could be implemented as extensions for Long.Companion
types.
I mean, potentially yes, but not necessarily. The issue with shape classes is that they’re not types, and as such they’re like pattern matching for generics, which is a great idea, but only half the deal. Here it’d be great to be able to accept a number without a floating part as a type, and have the compiler help you with that.
If this improvement is not deemed worthy enough of an ad-hoc solution, an alternative general way of solving this would be introducing union and intersection types.
So in this case I’d be able to write:
val Int|Long|BigInteger.pounds: Pounds get() = Pounds(this)
class Pounds(val amount: Int|Long|BigInteger)
or better, also with importable type aliases:
typealias IntegerNumber = Int|Long|BigInteger
val IntegerNumber.pounds: Pounds get() = Pounds(this)
class Pounds(val amount: IntegerNumber)
These 2 features, union & intersection types and importable type aliases would be a killer together, and can be used in so many ways. Also play great with dynamic casting, like:
val something: Float|Boolean|Double
if (something !is Boolean) {
println(something.toBigDecimal())
} else {
println(!something)
}