2

I want to do the following stuff using Scala's context-bound pattern:

    class Polynomial[T: Ring] {
        def apply[X: Ring with Includes[T]](x: X): X = ...
        ...
    }

This is a polynomial class which requires the coefficients are elements in a Ring T. When applying this polynomial to a element (evaluation), the type of the parameter x is required to be a ring, and elements of type T can be implicitly cast to type X. for example T = Double, X = SquareMatrix.

How can I impose more than one type constraints to a generic type parameter in Scala?

Tongfei Chen
  • 613
  • 4
  • 14

2 Answers2

3

It seems that [X: T] syntax is not enough for imposing two generic type constraints. Using two implicit parameters solved this problem:

   def apply[X](x: X)(implicit ring: Ring[X], conv: Includes[X, T]): X = {
     var xi = ring.one
     var sum = ring.zero
     for (i <- 0 to degree) {
       sum += xi * conv.from(coef(i))
       xi *= x
     }
    return sum
   }
Tongfei Chen
  • 613
  • 4
  • 14
0

The [X: T] syntax is simply syntactic sugar for requiring an implicit parameter of type T[X]. For example, f and f2 below are identical:

 def f[T: X]
 def f2[T](implicit xt: X[T])

As for your code, if you explicitly write out the implicit parameter you will be able to express your constraints:

class Polynomial[T: Ring] {
    def apply[X](x: X)(implicit xt: Ring[X] with Includes[T]): X = ...
}

Note that you aren't imposing more than one constraint on either X or T, your constraint is simply too complex for the context-bound syntactic sugar. However, Scala does allow you to impose as many context-bounds on type parameters as you like, and you can combine them with upper- and lower-bounds as well:

def f[T >: List[Int] <: AnyRef : Ordering : List] = ???
wingedsubmariner
  • 13,350
  • 1
  • 27
  • 52