Search code examples
scalagenericspolymorphismtype-parameter

Type parameter issue in Scala with generic function


I'm trying to come up with a generic function (toBitSet) using type parameter T.

 def toBitSet[T:Integral](x:T, valueBitwidth:Int, filterBitwidth:Int, bigEndian:Boolean = true, shift:Int = 0) = {   
    BitSet((for (i <- 0 to (valueBitwidth - 1) if (((x & 0xFF) >> i) & 1) == 1) yield (i + shift)): _*)
  }

byteToBitSet and shortToBitSet functions are specializaton of the generic function.

  def byteToBitSet(x:Byte, filterBitwidth:Int, bigEndian:Boolean = true, shift:Int = 0) = {
    toBitSet[Byte](x = x, valueBitwidth = 8, filterBitwidth = filterBitwidth, bigEndian = bigEndian, shift = shift)
  }
  def shortToBitSet(x:Short, filterBitwidth:Int, bigEndian:Boolean = true, shift:Int = 0) = {
    toBitSet[Short](x = x, valueBitwidth = 16, filterBitwidth = filterBitwidth, bigEndian = bigEndian, shift = shift)
  }

However, Scala doesn't understand the operators (>>, &, ==, +) on type T to show an error message. I specified that T is Integral type, but it doesn't work.

enter image description here

How to solve this issue?


Solution

  • The type signature def func[T: Integral](arg: T) = {} is actually a syntactic shorthand for: def func[T](arg: T)(implicit ev: Integral[T]) = {} ("ev" is often chosen as the name for this "evidence" argument.)

    The Integral trait outlines what operations you then use on elements of type T. Example: addition is ev.plus(t1, t2)

    If you import Integral.Implicits._ then you can use the more natural infix notation: t1 + t2

    Unfortunately, the Integral trait doesn't include bit-wise operations like & and >>.

    If you can modify your algorithm to use only those available ops you'll get the function you're after.