4 ms·
One powerful feature I don't see being used very often is simulating typeclasses via contraints on generic types: public static IEnumerable<CalculatedTax>
by jb55 15y ago
One powerful feature I don't see being used very often is simulating typeclasses via contraints on generic types:
public static IEnumerable<CalculatedTax> CalculateTaxes<T>(this T t)
where T : IOrderItems, IAddress {}
This adds an extension method to any type that implements those interfaces. Using this technique I have been able to make my interfaces much smaller and have generic functions which apply to many different types.
Here's what it would might look like in Haskell:
calculateTaxes :: (OrderItems a, Address a) => a -> [CalculatedTax]
- chown 15y agoHow should one call or use it? Any example or a link?
- jb55 15y agohttps://gist.github.com/1313735 https://gist.github.com/1313735 Here's a full example in some production code. I ended up doing it this way to simplify some crazy legacy code. There were a bunch of different classes that provide order items and extended prices in different ways. With this setup as long as those types implement the necessary interfaces, they get those extension methods for free.
- mattmanser 15y agoSimply: orderItems.CalculateTaxes(); If orderItems implements IOrderItems. Just have to include a using statement for the namespace it's in, it's an extension method. Look them up if you're unsure. I didn't know you could do that with them, it's pretty cool. Although it's kinda what abstract classes and inheritance is for, but you can only inherit from one in C#.
- sreque 15y agoTo be fair, this doesn't really simulate type classes, it's just allowing you to specify in a method signature that a particular type implements more than one interface. To simulate type classes, you would have to have the ability to declare statically that an existing type, potentially one you have no control over, implements an interface, and to then have the static extension methods apply to that type automatically. This is in effect what Scala's implicits do that allows them to simulate type classes.
- jb55 15y agoIndeed, it really only simulates the function type constraint aspect of Haskell typeclasses. Fortunately most of the time I have direct access to the implementation, and can throw an interface on a type when I need it. This is effectively the expression problem. You can always solve it by using a wrapper class, although it's a bit inconvenient.