0
votes

I'm trying to get the hang of Scala traits and case classes. Below is a followup to this question.

Suppose I have a simple class and an object that extends it.

sealed trait Operations{
    def add(a:Double,b:Double):Double
    def multiply(a:Double,b:Double):Double
}

case object CorrectOperations extends Operations{
    def add(a:Double,b:Double):Double = a+b
    def multiply(a:Double,b:Double):Double= a*b
}

Now I have some function that will make use of any object of type Operations, such as,

def doOperations(a:Double,b:Double, op:Operations)={ op.multiply(a,b) - op.add(a,b)}.

This works well, but my question is how to generalize the types of trait Operations, so we're not just talking about Doubles. So i'd like to have generic types for trait Operations and then type specification for each object.

Using type generics, I tried

sealed trait Operations[T]{
  def add(a:T,b:T):T
  def multiply(a:T,b:T):T
}

case object CorrectOperations extends Operations[Double]{
    def add(a:Double,b:Double):Double = a+b
    def multiply(a:Double,b:Double):Double= a*b
}

def doOperations[T](a:T,b:T, op:Operations[T])={ op.multiply(a,b) - op.add(a,b) },

with a compile error at doOperations - "value - is not a member of type parameter T".

So we know that op.multiply(a,b) will return type T, and the error would indicate that type T has no .- method.

How should I be thinking about achieving this generalization of trait Operations ? Thanks

2

2 Answers

2
votes

In the context of your problem, you should introduce a subtract method into your Operations trait, so that you can provide evidence that T has such a method (well it doesn't, but a method that does a subtraction from to T from another).

sealed trait Operations[T] {
    def add(a: T, b: T): T
    def multiply(a: T, b: T): T
    def subtract(a: T, b: T): T
}

case object CorrectOperations extends Operations[Double]{
    def add(a: Double, b: Double): Double = a + b
    def multiply(a: Double, b: Double): Double = a * b
    def subtract(a: Double, b: Double): Double = a - b
}

def doOperations[T](a: T, b: T, op: Operations[T]) =
    op.subtract(op.multiply(a,b), op.add(a,b))

This is basically what the Numeric trait does.

1
votes

The problem you are running into is that there is no - (minus) operation in your type class to subtracting your multiply result from your add result fruitlessly looks for that operator on type T.

Try adding minus to your type class:

sealed trait Operations[T]{
  def add(a:T,b:T):T
  def multiply(a:T,b:T):T
  def minus(a:T,b:T):T
}

def doOperations[T](a:T,b:T, op:Operations[T])=
  op.minus(op.multiply(a,b) - op.add(a,b))