Closed ja72 closed 3 years ago
Wrapping all of the primitive types with interface implementations would be a CLR concern, you could request that here: https://github.com/dotnet/runtime/issues
However, doing so would have some big disadvantages. Calling a method through an interface like this requires boxing the value type which incurs an allocation on the heap, plus the virtual dispatch of calling the instance member on the interface. Generic specialization on structs may help to avoid some of this.
The C# team is proposing solving these kinds of problems in a different way: https://github.com/dotnet/csharplang/issues/1711 The part that's relevant is under the heading "An example: Numeric abstraction" that defines a numeric monoid.
The C# team is proposing solving these kinds of problems in a different way: #1711 The part that's relevant is under the heading "An example: Numeric abstraction" that defines a numeric monoid.
Well, at least the team recognize the shortcoming and are working on at. Thanks for the issue# link. I heard of monoids before and had no idea what they were talking about, but I am beginning to understand.
// Floating point types public interface IReal : INumeric { } public interface IFloat : IReal { } // float public interface IDouble : IReal { } // double
Nit: should be ISingle
as that is the proper name. But also, why would there be IDouble
? I get IReal
, but surely IDouble
will only be implemented by Double
// Floating point types public interface IReal : INumeric { } public interface IFloat : IReal { } // float public interface IDouble : IReal { } // double
Nit: should be
ISingle
as that is the proper name. But also, why would there beIDouble
? I getIReal
, but surelyIDouble
will only be implemented byDouble
IReal
is there to distinguish between scalar values and non-scalar such as IComplex
or IDual
.
Then under IReal
you might have ISingle
for 32-bit floats, IDouble
for 64-bit floats and maybe IExtended
for 80-bit floats. You are correct that IFloat
might be confusing.
IReal
also doesn't correctly capture things like NaN
. Additionally, depending on who you ask PositiveInfinity
and NegativeInfinity
may or may not quantify as "real numbers".
IReal
also doesn't correctly capture things likeNaN
. Additionally, depending on who you askPositiveInfinity
andNegativeInfinity
may or may not quantify as "real numbers".
A NaN
is an artifact of a concrete type such as float
or double
, so it should be captured under the corresponding types, and it has nothing to do with contracts the interfaces present.
It is not just an artifact, it is a fundamental value of the float
and double
type and therefore something that could be exposed via any IReal
interface that was created from a float
, double
, or from performing certain operations on them.
It is something that would need to be understood and rationalized with these interfaces if they were ever to become a real thing.
I like the idea that primitive types implement a set of standardized interfaces this could be useful in generic constraints..
...but public interface IComplex: IReal { }
(for example) is mathematically wrong.
Not every complex value is a real value. (only those with imaginary = 0)
Instead the reverse is true: every real value is also a complex one!
Difficult to known in advance, which interface hierachy is needed.
I like the idea that primitive types implement a set of standardized interfaces this could be useful in generic constraints..
...but
public interface IComplex: IReal { }
(for example) is mathematically wrong. Not every complex value is a real value. (only those with imaginary = 0) Instead the reverse is true: every real value is also a complex one!Difficult to known in advance, which interface hierarchy is needed.
You are right in that IReal
made it seem like a real number, so I renamed it to IFloat
since it represents the common ancestor for all floating-point numbers. In that sense, you represent a complex number as two floating-point numbers, and hence it still has the behavior of floating-point numbers and hence inherits from IFloat
.
Wrapping all of the primitive types with interface implementations would be a CLR concern, you could request that here: https://github.com/dotnet/runtime/issues
Is there a way to migrate the issue, or shall I close and re-post in the CLR hub?
@ja72 You might want to read https://github.com/dotnet/runtime/issues/14723 first.
See also https://github.com/dotnet/runtime/issues/25058 and https://github.com/dotnet/runtime/issues/18244.
Clsoing as duplicate of dotnet/runtime#14723 and other issues on dotnet/runtime
The intent is to help with generic constrains, extension methods, and generally handling primitives types.
The specialized libraries can hook into this to defined other custom types that will play well within the existing framework
Additionally, it would make sense that arithmetic operators and comparisons be required to be implemented to create concrete types from the
INumeric
interface.The addition of the above interfaces and implementation with primitive types would make the CLR far more flexible and extensible for scientific computing applications. It would allow for more generic code writing such as:
and the compiler would know how to bind the arithmetic operators or do the implicit conversions (like from float to double) to make the code work without having to write different versions for different numeric types.