Conforming `Real` to `Differentiable`
stephentyrone opened this issue · comments
As of #111, Complex
now conforms to Differentiable
if the underlying RealType
does:
#if canImport(_Differentiation)
import _Differentiation
extension Complex: Differentiable
where RealType: Differentiable, RealType.TangentVector == RealType {
public typealias TangentVector = Self
}
After some offline discussion with @rxwei, I'm considering the merits of making Real
refine Differentiable
:
#if canImport(_Differentiation)
public protocol Real: FloatingPoint, RealFunctions, AlgebraicField,
Differentiable where TangentVector == Self {
}
#else
public protocol Real: FloatingPoint, RealFunctions, AlgebraicField {
}
#endif
This would simplify the conformance for Complex
by making it unconditional:
#if canImport(_Differentiation)
import _Differentiation
extension Complex: Differentiable {
public typealias TangentVector = Self
}
and make Real
more powerful itself, and so simplify a number of use sites somewhat. But it would imply a modest burden for any third-party types conforming to Real
, because it does increase the API surface. I think that this trade-off makes sense, but I'd like to get people's feedback before adding the conformance.
It's also slightly weird to have a conformance that depends on availability of a module. Because Swift Numerics is not stable, and is distributed as source, this shouldn't pose a significant problem, but we might be painting ourselves into a corner w.r.t. possibly moving Real
into the standard library at some future point. Language changes may make this less of an issue by that time, but we can't necessarily depend on that.
Thanks in advance!
Is there any way to make this all live in a separate overlay module, eg. DifferentiableNumerics
, which people can import if they want?
Is there any way to make this all live in a separate overlay module, eg.
DifferentiableNumerics
, which people can import if they want?
It is technically possible to add derivatives and Differentiable
conformances retroactively, but retroactive refinement isn't possible so we would not be able to achieve the benefits of making Real
refine Differentiable
as proposed in this issue.
What @rxwei said. The closest we could come with the language we have today would be to add a DifferentiableReal protocol.
It may be possible to put refinements in a separate module at some future point (the ABI allows it, IIRC), but I can’t really speculate on when we’ll get the necessary language features to enable it.
If we get the fixes to typechecker performance and shadowing rules that allow us to incorporate Real into the Standard Library, but not any kind of retroactive protocol refinement... where does that leave us if we go in this direction?
@kylemacomber In the worst case scenario you describe, we would drop the Differentiable
refinement for Real in the standard library, and add a DifferentiableReal
protocol in the _Differentiation module that's just Real & Differentiable
. Anyone using the conformance would need to update the constraint in their code to use DifferentiableReal
instead. That's a source and ABI break, but the swift numerics RealModule isn't resilient, and isn't source-stable, so clients have to expect such changes (even though we try to keep them to a minimum).
Tagging @jckarter, who can maybe provide more context around any ABI issues we could run into if we do this.
Have we implemented the ability to add retroactive refinements without breaking ABI yet? cc @slavapestov
Ping @slavapestov
Unfortunately this change would be an ABI break. We do not allow retroactively adding new inherited protocols.
Unfortunately this change would be an ABI break. We do not allow retroactively adding new inherited protocols.
Does the ABI have space for retractive refinement to be implemented in the future?
Closing this for now.