28 ms·
Actually you can do ad-hoc polymorphism in C# (and I assume Java too, although I've not used it). Here's an example of implementing an Eq and Ord 'type class'
by louthy 9y ago
Actually you can do ad-hoc polymorphism in C# (and I assume Java too, although I've not used it). Here's an example of implementing an Eq and Ord 'type class' in C#, with 'class instances' of OrdInt and OrdString. Then a simple generic bubble-sort function which works on any type that has an Ord instance:
public interface Eq<A>
{
bool Equals(A x, A y);
}
public interface Ord<A> : Eq<A>
{
bool GreaterThan(A x, A y);
bool GreaterThanOrEq(A x, A y);
bool LessThan(A x, A y);
bool LessThanOrEq(A x, A y);
}
public struct OrdInt : Ord<int>
{
public bool Equals(int x, int y) => x == y;
public bool GreaterThan(int x, int y) => x > y;
public bool GreaterThanOrEq(int x, int y) => x >= y;
public bool LessThan(int x, int y) => x < y;
public bool LessThanOrEq(int x, int y) => x <= y;
}
public struct OrdString : Ord<string>
{
public bool Equals(string x, string y) => x == y;
public bool GreaterThan(string x, string y) => x.CompareTo(y) > 0;
public bool GreaterThanOrEq(string x, string y) => x.CompareTo(y) >= 0;
public bool LessThan(string x, string y) => x.CompareTo(y) < 0;
public bool LessThanOrEq(string x, string y) => x.CompareTo(y) <= 0;
}
public static class Testing
{
public static void Test()
{
var x = new[] { 3, 8, 1, 2, 10 };
var y = new[] { "mary", "had", "a", "little", "lamb" };
BubbleSort<OrdInt, int>(x);
BubbleSort<OrdString, string>(y);
}
public static void BubbleSort<OrdA, A>(A[] values) where OrdA : struct, Ord<A>
{
bool swap;
do
{
swap = false;
for (var i = 0; i < values.Length - 1; i++)
{
var x = values[i];
var y = values[i + 1];
if (default(OrdA).GreaterThan(x, y)) // Ad-hoc polymorphic call to GreaterThan
{
swap = true;
values[i] = y;
values[i + 1] = x;
}
}
}
while (swap);
}
}
- DaiPlusPlus 9y agoBut you just proved my point: your OrdString and OrdInt types there are implementations of the Decorator pattern (just using interfaces instead of superclasses).
- louthy 9y agoNo they're not, they are not wrapping an object instance, they are providing ad-hoc functionality only. The generic parameters provided to BubbleSort are constraining the arguments and allowing access to the ad-hoc functionality, something that can't be done with inheritance unless you own the type. This is exactly how traits, implicits, type-classes, class-instances, and concepts work in other languages like Scala, Haskell, etc.