Problem
The Numeric
protocol today refines ExpressibleByIntegerLiteral
. This makes sense for scalars, but does not work well with high-dimensional data structures such as vectors and tensors.
Let's think of a scenario where there's a VectorNumeric
protocol that refines Numeric
. A vector numeric protocol needs a couple of extra operators, particularly arithmetic operators that take a scalar on one side:
protocol VectorNumeric : Numeric {
associatedtype ScalarElement : Numeric
init(_ scalar: ScalarElement)
static func + (lhs: Self, rhs: ScalarElement) -> Self
static func + (lhs: ScalarElement, rhs: Self) -> Self
static func - (lhs: Self, rhs: ScalarElement) -> Self
static func - (lhs: ScalarElement, rhs: Self) -> Self
static func / (lhs: Self, rhs: ScalarElement) -> Self
static func / (lhs: ScalarElement, rhs: Self) -> Self
}
Here's a conforming type:
extension Vector : Numeric {
static func + (lhs: Vector, rhs: Vector) -> Vector {
...
}
static func + (lhs: Vector, rhs: ScalarElement) -> Vector {
...
}
...
init(integerLiteral: ScalarElement) {
...
}
}
Ok, now let's do some arithmetics:
let x = Vector<Int>(...)
x + 1
This fails because +
is ambiguous. It can be either + (_: Self, _: ScalarElement)
and + (_: Self, _: Self)
.
static func + (lhs: Self, rhs: ScalarElement) -> Self
static func + (lhs: Self, rhs: Self) -> Self
Possible solutions
-
Move
ExpressibleByIntegerLiteral
refinement fromNumeric
toBinaryInteger
, just like howBinaryFloatingPoint
refinesExpressibleByFloatLiteral
.Numeric
will no longer require conforming types to be convertible from integer literals. -
Remove overloaded self + scalar arithmetic operators, leaving only self + self. This will resolve ambiguity but makes the vector library hard to use and not match mathematical requirements.
What does everyone think?