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
ExpressibleByIntegerLiteralrefinement fromNumerictoBinaryInteger, just like howBinaryFloatingPointrefinesExpressibleByFloatLiteral.Numericwill 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?