Trouble implementing Summable

67 views Asked by At

I'm trying to implement classes DistanceCM and DistanceMM, and I want these to be summable interchangeably, as long as they both inherit from Distance.

However, I get this error:

"Error:(46, 76) ceylon: type parameter 'Other' of declaration 'Summable' has argument 'Distance' which is not assignable to upper bound 'Summable' of 'Other'"

...which I can't decipher... The error message refers to this line in the code below:

shared actual Distance plus(Distance other) 

This is the current code:

abstract class Distance() of DistanceMM | DistanceCM {
    shared formal Distance multiplyScalar(Float scalar);
}


class DistanceMM(variable Float val) extends Distance() satisfies Summable<Distance>
{
    shared Float distanceInMillimeters;
    shared Float distanceInCentimeters;

    switch (unit)
    case (millimeter) {
        distanceInMillimeters => val;
        distanceInCentimeters => val / 10;
    }
    case (centimeter) {
        distanceInMillimeters => val * 10;
        distanceInCentimeters => val;
    }


    shared actual DistanceMM multiplyScalar(Float scalar) {
        val = val * scalar;
        return this;
    }


    shared actual Distance plus(Distance other) {
            switch (other)
            case (DistanceMM) {
                return DistanceMM(val + other.distanceInMillimeters(), unit);
            }
            case (DistanceCM) {
                return DistanceMM(val + other.distanceInCentimeters(), unit);
            }
    }
}


class DistanceCM(variable Float val) extends Distance() satisfies Summable<Distance>
{
    shared Float distanceInMillimeters;
    shared Float distanceInCentimeters;

    switch (unit)
    case (millimeter) {
        distanceInMillimeters => val;
        distanceInCentimeters => val / 10;
    }
    case (centimeter) {
        distanceInMillimeters => val * 10;
        distanceInCentimeters => val;
    }

    shared actual DistanceCM multiplyScalar(Float scalar) {
        val = val * scalar;
        return this;
    }
    // implementation missing
}
1

There are 1 answers

0
gdejohn On BEST ANSWER
interface Summable<Other> of Other​ given Other satisfies Summable<Other>

Notice the constraint (the given clause). You're claiming that DistanceMM satisfies Summable<Distance>, but Distance doesn't satisfy the constraint on Other (Distance doesn't satisfy Summable<Distance>). Try this:

interface Distance of Centimeter | Millimeter satisfies Summable<Distance> {}

class Centimeter() satisfies Distance {
    shared actual Distance plus(Distance other) => nothing;
}

class Millimeter() satisfies Distance {
    shared actual Distance plus(Distance other) => nothing;
}