Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Scala, how do i tell an abstract base class that type parameter T supports implicit conversion from Int (or Float, or...)?

I'm having difficulty transitioning from the world of C++/Templates to scala. I'm used to being able to use any operation on a template parameter T that I want, as long as anything I use to instantiate T with supports those operations (compile-time Duck typing, basically). I cannot find the corresponding idiom in Scala that will allow me to define an abstract class with a single type parameter, and which expects a certain interface for type T.

What I have almost works, but I cannot figure out how to tell the abstract class (Texture[T <: Summable[T]]) that T supports conversion/construction from an Int. How can I add the implicit conversion to the trait Summable so that Texture knows T supports the conversion?

trait Summable[T] { 
   def += (v : T) : Unit
   def -= (v : T) : Unit   
}

object Int4 { implicit def int2Int4(i : Int) = new Int4(i, i, i, i) }

class Int4 (var x : Int, var y : Int, var z : Int, var w : Int) extends Summable[Int4] {
   def this (v : Int) = this(v, v, v, v)
   def += (v : Int4) : Unit = { x += v.x; y += v.y; z += v.z; w += v.w }
   def -= (v : Int4) : Unit = { x -= v.x; y -= v.y; z -= v.z; w -= v.w } 
}

abstract class Texture[Texel <: Summable[Texel]] {
   var counter : Texel
   def accumulate(v : Texel) : Unit = { counter += v }
   def decrement() : Unit = { counter -= 1 } //< COMPILE ERROR HERE, fails to find implicit
}

class Int4Target extends Texture[Int4] {
   var counter : Int4 = new Int4(0, 1, 2, 3)
}
like image 341
Fooberman Avatar asked Jan 18 '23 12:01

Fooberman


1 Answers

You can define an implicit constructor parameter like this

abstract class Texture[Texel <: Summable[Texel]](implicit int2Texel: Int => Texel) {
//...

This essentially tells the compiler that in order to construct an instance of Texture, there must be an implicit conversion function available from Int to Texel. Assuming you have such a function defined somewhere in scope (which you do), you should no longer get a compile error.

Edit2: Ok I originally misread your code, you actually only need one implicit parameter from Int => Texel. Your code compiles for me with the above modification.

Edit: You'll actually need 2 conversion functions, one from Texel => Int and another from Int => Texel in order to properly reassign the var

like image 112
Dan Simon Avatar answered Jan 29 '23 10:01

Dan Simon