We would like to create an architecture with some trait Shape
that allows us to calculate the area of a shape depending on some context. We allow each Shape to have its own type for scalars (e.g. radius type for circle, side type for square, etc.).
trait ShapeTypes {
type Scalar;
}
trait Shape: ShapeTypes {
fn area<Ctx: ShapeTypes>(&self, unit: Ctx::Scalar) -> Ctx::Scalar
where
Ctx::Scalar: From<Self::Scalar>;
}
As an example, let's take Circle
with radius of type f64
:
struct Circle(f64);
impl ShapeTypes for Circle {
type Scalar = f64;
}
impl Shape for Circle {
fn area<Ctx: ShapeTypes>(&self, unit: Ctx::Scalar) -> Ctx::Scalar
where
Ctx::Scalar: From<Self::Scalar>,
{
// here we would perform something like
// unit * self.0.into()
unimplemented!()
}
}
At some point, we'll have multiple types of shapes and it'd be good to have some general structure for them: AnyShape
implementing the Shape
trait as well.
enum AnyShape {
Circle(Circle),
}
impl Shape for AnyShape {
fn area<Ctx: ShapeTypes>(&self, unit: Ctx::Scalar) -> Ctx::Scalar
where
Ctx::Scalar: From<Self::Scalar>,
{
match self {
AnyShape::Circle(circle) => circle.area::<Ctx>(unit),
}
}
}
Also, at some point, we'd like to separate the shapes into their own crates so we can test their implementations separately.
The issue is that Rust doesn't allow the naive solution to this problem, so when trying to implement the Shape
trait for the AnyShape
structure for delegating calls to the sub-types, the error appears:
the trait bound `<Ctx as ShapeTypes>::Num: From<f64>` is not satisfied
.
How would one approach this in Rust?