I am trying to make a typeclass that defines various arithmetic operations for pairs of input types. Importantly, that typeclass needs to also define what the output type is.
I’ve got the following type class for this:
trait Arithmetic[L, R] {
type Output
def add(x: L, y: R): Output
def sub(x: L, y: R): Output
}
And this works fine to define functions like so:
def add[X, Y](x: X, y: Y)(using arith: Arithmetic[X, Y]): arith.Output = arith.add(x, y)
But if I try to use this in a class definition, extending a base class using the output type, then I get an error message:
class Value[T](value: T)
class AddThing[X, Y](x: X, y: Y)(using arith: Arithmetic[X, Y]) extends Value[arith.Output](arith.add(x, y))
non-private class AddThing refers to private given instance arith
in its type signature Value[AddThing.this.arith.Output] {...}
I’d love help with what I should be doing here. Full (but minimal) example of the type of thing I’m trying to do is here. Thanks 
Well, I thought you just need to make arith
public, so you can refer to the Output
type on the public signature of AddThing
.
class AddThing[X, Y](x: X, y: Y)(using val arith: Arithmetic[X, Y]) extends Value[arith.Output](arith.add(x, y))
But, that seems to trigger this error message:
The type of a class parent cannot refer to constructor parameters, but Value[AddThing.this.arith.Output] refers to arith
Thanks. And is there any way to work around that restriction? For my use case being able to pass it to the superclass is pretty essential.
@obeattie
Is the intent here to work with boxes of values in the form of Value
, or does the planned API for AddThing
impart anything more for client code using it?
If just a Value
will do, how about simply:
def summedValue[X, Y](x: X, y: Y)(using arith: Arithmetic[X, Y]): Value[arith.Output] = new Value(arith.add(x, y))
Would that do?
Going a little further, would it be feasible for client code to work in the domain of left, right and result types directly as generic code, delegating to a given Arithmetic
instance. Essentially this is a tagless final approach, with Arithmetic
as an object algebra. What does Value
add from the point of view of client code?
Of course, I don’t have the big picture of what you are trying to do - this is a probably a quite reduced example - so take my advice with a pinch of salt.
1 Like