An example of typeclasses/traits/protocols/concepts in D with interfaces
sighoya
sighoya at gmail.com
Wed Dec 23 14:20:39 UTC 2020
```D
import std.stdio;
public interface Number(T)
{
T add(T)(T n1,T n2);
T sub(T)(T n1,T n2);
T mul(T)(T n1,T n2);
T div(T)(T n1,T n2);
}
public class DoubleNumber:Number!double
{
static double add(double n1,double n2)
{
return n1+n2;
}
static double sub(double n1,double n2)
{
return n1-n2;
}
static double mul(double n1,double n2)
{
return n1*n2;
}
static double div(double n1,double n2)
{
return n1/n2;
}
}
class IntNumber:Number!int
{
static int add(int n1,int n2)
{
return n1+n2;
}
static int sub(int n1,int n2)
{
return n1-n2;
}
static int mul(int n1,int n2)
{
return n1*n2;
}
static int div(int n1,int n2)
{
return n1/n2;
}
}
//Typeclasss instances
alias Instance(T:Number!int) = IntNumber;
alias Instance(T:Number!double) = DoubleNumber;
T squareCompiletime(T, alias Implementor = Instance!(Number!T))(T
number)
{
return Implementor.mul(number,number);
}
T squareRuntime(T)(T number,Instance!(Number!T) instance = new
Instance!(Number!T))
{
return instance.mul(number,number);
}
int main()
{
writeln(squareCompiletime(3));
writeln(squareRuntime(3));
writeln(squareCompiletime(3.0));
writeln(squareRuntime(3.0));
return 0;
}
```
Some things that irk me:
1.) Can't we import aliases from other modules or am I just too
dumb to see how?
2.) it would be nice to unscope the methods of a type, e.g. `T
square(T, unscope alias Implementor = ...)` s.t. we don't have to
prefix it all the time with Implementor, the same for the runtime
version of square.
This should also work with operators, I've left them out here.
Clearly, language site implicit instance resolution is often more
convenient, but D people like it more explicit. Moreover,
language site instance resolution has to be implemented carefully
to choose the appropriate instances with regard to the current
scope (a.k.a global coherence problem) and most languages simply
don't get that right, we can do it better, manually :).
I think it is also possible to require typeclass dependencies
like in Rust, e.g. if A gets implemented then B also, or each
Number must be Equatable:
`public interface Number(T) where Instance!(Eq!T)`
More information about the Digitalmars-d
mailing list