apple / swift-numerics

Advanced mathematical types and functions for Swift

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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!

Tagging @NevinBR and @xwu, who are more likely to be effected by this if we do it than most people. (Xiaodi, I know you have a lot going on these days, so no need to reply unless you want a diversion.)

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

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.