3

It's a real shame that in .Net there is no polymorphism for numbers, i.e. no INumeric interface that unifies the different kinds of numerical types such as bool, byte, uint, int, etc. In the extreme one would like a complete package of abstract algebra types.

Joe Duffy has an article about the issue:

http://www.bluebytesoftware.com/blog/CommentView,guid,14b37ade-3110-4596-9d6e-bacdcd75baa8.aspx

How would you express this in C#, in order to retrofit it, without having influence over .Net or C#?

I have one idea that involves first defining one or more abstract types (interfaces such as INumeric - or more abstract than that) and then defining structs that implement these and wrap types such as int while providing operations that return the new type (e.g. Integer32 : INumeric; where addition would be defined as

public Integer32 Add(Integer32 other)
{
    return Return(Value + other.Value);
}

I am somewhat afraid of the execution speed of this code but at least it is abstract.

No operator overloading goodness...

Any other ideas?

.Net doesn't look like a viable long-term platform if it cannot have this kind of abstraction I think - and be efficient about it.

Abstraction is reuse.

update:

This is an example implementation type signature so far:

public struct Integer32 : INumeric<Integer32, Int32>, IOrder<Integer32, Int32>

Compensating for the lack of covariant return types.

plannapus
  • 18,529
  • 4
  • 72
  • 94
Bent Rasmussen
  • 5,538
  • 9
  • 44
  • 63
  • 1
    Is there a reason you wouldn't use a generic interface for this? Have you considered and rejected generics? – overslacked Mar 08 '10 at 21:11
  • 1
    That's the thing, I am using generics, it's just that for every specific type, such as Int32, I implement this interface in a struct such that public struct Integer32 : INumeric, ... The strange definition is also due to the fact that C# doesn't have "covariant return types" - I believe this is the term. In Eiffel the syntax "like Current" is possible. Not so in C#, as far as I can see. – Bent Rasmussen Mar 08 '10 at 21:57

3 Answers3

5

Someone has already gone to the effort of writing something which may solve your delemma. It's called Generic Operators, and is available in the Miscellaneous Utility Library.

Nick
  • 5,875
  • 1
  • 27
  • 38
  • That is quite ingenious. And this solution is efficient and performant? – Bent Rasmussen Mar 08 '10 at 21:41
  • @Bent - I can't speak to the performance characteristics directly. You'll have to investigate that yourself. – Nick Mar 08 '10 at 21:42
  • Thanks for the Tip, Nick. It looks like the C# equivalent of C++ templates - in a way. I never thought this was possible without a macro processor. Great idea. – Bent Rasmussen Mar 08 '10 at 21:53
  • @Brent - Well... Generics are in fact the closest thing to C++ templates that exist in C#. The problem is that you can't use overloaded operators in a generic method. The class library I mentioned provides a workaround to that one limitation. – Nick Mar 08 '10 at 22:21
  • 1
    Speaking as "Someone" - yes, it is generally pretty quick. My `Reflection.Emit` is much stronger these days, though, so maybe I'll back-port it to .NET 2.0. It is certainly faster than `dynamic`, especially when `Nullable` gets involved (`dynamic` slows down significantly). – Marc Gravell Mar 09 '10 at 06:18
  • I'd like to do some comparisons between your dynamic compilation technique and the struct wrapping technique I'm applying. – Bent Rasmussen Mar 09 '10 at 11:37
  • @Nick I don't consider generics very comparable to templates - they achieve some of the same things but templates appear more expressive but less semantically kosher in the sense that it's some kind of syntactic transformation that is then checked to see if it makes sense. I seem to remember that in C++ template errors don't give you the best diagnostics messages. But yes, in some way you can compare them -- but I think Marc's technique is closer to C++ templates because it's a separate compilation phase of sorts. But as long as it's fast... – Bent Rasmussen Mar 09 '10 at 11:43
1

The csharp language team is already looking into this. If you want a view onto the future of type classes in C# start reading at

https://github.com/dotnet/csharplang/issues/164

enter image description here

It seems to have the support of Mads Torgesson so it's not just a random post by a wandering Haskell fanboy.

The example given of a typeclass or shape in C# land is

public shape SGroup<T>
{
    static T operator +(T t1, T t2);
    static T Zero { get; }
}

notice this is not like an interface. It is declaring static method that belong to SGroup. Read on for more details and discussion.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
bradgonesurfing
  • 30,949
  • 17
  • 114
  • 217
0

If you plan to use C# 4.0 then you can easily simulate generic mathematical operations using dynamic. Here is an example of a simple addition function (for more information see this blog):

public static T Add<T>(T a, T b) {
  dynamic ad = a;
  dynamic bd = b;
  return ad + bd;
}

I haven't played with this, so I can't say much about the performance. There will certainly be some performance price for using dynamic, but I think the DLR should be able to do very effective optimizations if you'll invoke the function multiple times. In fact, I won't be surprised if it had similar performance profile as Generic Operators mentioned above.

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • 1
    Re performance - when I checked on a fairly early beta, there was a noticeable slow-down if `T` turned out to be `Nullable` for some `X`, but otherwise it wasn't *too* bad (for moderate usage, at least). – Marc Gravell Mar 09 '10 at 06:19
  • Yes I know about this but dynamic is simply too slow, it's a performance killer. – Bent Rasmussen Mar 09 '10 at 11:35
  • ...Well I think it is... And don't like to cheat the type system like this. – Bent Rasmussen Mar 09 '10 at 11:44
  • I'm afraid you'll be cheating the type system anyway. _Generic operators_ are pretty same in this sense. In F#, you can use _static constraints_ (resolved at compile-time) which aren't cheating (but have other limitations) or _numeric associations_ which are like _Generic Operators_. See for example: http://stackoverflow.com/questions/2225949/does-f-have-generic-arithmetic-support – Tomas Petricek Mar 09 '10 at 12:48
  • @Thomas: Thanks. I'm very impressed with F#'s units of measure and some other aspects of it. - I do however prefer the more "modelling-oriented" approach of C#. – Bent Rasmussen Mar 10 '10 at 19:14