Attempt to expand a shared array

I am sure it is very easy to do this in Scala, but I can’t understand what kind of hints of the type system need to be done for this to work.

I want to have an abstract Printable class, and then implicitly convert other classes to it. More specifically, I want to implicitly convert Byte to Printable and Array [Byte] to Printable.

So, I did this:

abstract class Printable{
    def print():String
}
class PrintableByte(b:Byte) extends Printable{
    def print() = "" /*return something*/
}
implicit def printableByte(b:Byte) = new PrintableByte(b)

class PrintableArray(a:Array[Printable]) extends Printable{
    def print() = {
        for(i <- 0 until a.length) a(i).print()   // no problems here
        "" /*return something*/
    }
}
implicit def printableArray(a:Array[Printable]) = new PrintableArray(a)

However:

val b:Byte = 0
b.print()   //no problem here
val a= new Array[Byte](1024)
a.print()   //error: value print() is not a member of Array[Byte]

I expected the type system to be able to understand that Array [Byte] is implicitly an array of [Printable] and implicitly Printable.

What am I missing?

+3
source share
4 answers

Only my two cents:

abstract class Printable{
    def print: String
}

class PrintableArray[T <% Printable](a: Array[T]) extends Printable{
    def print = (for(x <- a) yield x.print) mkString
}
implicit def printableArray[T <% Printable](a: Array[T]) = new PrintableArray(a)

class PrintableByte(b: Byte) extends Printable{
    def print = "%#02x" format b
}
implicit def printableByte(b:Byte) = new PrintableByte(b)

class PrintableInt(i: Int) extends Printable{
    def print = "%#08x" format i
}
implicit def printableInt(i: Int) = new PrintableInt(i)

And then:

scala> val b: Byte = -1
b: Byte = -1

scala> val i: Int = 100
i: Int = 100

scala> val bArr = Array[Byte](11,22,33,44)
bArr: Array[Byte] = Array(11, 22, 33, 44)

scala> val iArr = Array[Int](111111,222222,333333,444444)
iArr: Array[Int] = Array(111111, 222222, 333333, 444444)

scala> b print
res0: String = 0xff

scala> i print
res1: String = 0x000064

scala> bArr print
res2: String = 0xb0x160x210x2c

scala> iArr print
res3: String = 0x01b2070x03640e0x0516150x06c81c

scala>
+5
source

, , , ( , ) Array, :

class PrintableArray[T <% Printable](a:Array[T]) {...}
implicit def printableArray[T <% Printable](a:Array[T]) {...}

, () T Printable :

class PrintableArray[T](a:Array[T])(implicit t2printable: T => Printable) {...}
implicit def printableArray[T](a:Array[T])(implicit t2printable: T => Printable) {...}

, , !

+3

a.print() : Byte PrintableByte, Array[PrintableByte] PrintableArray, implicits . , , , .

+1

Randall already gave a reason why your code doesn't work the way it is. In your case, you can simply change your PrintableArray as follows, and then it works as you described (using scala 2.8.0.RC7):


abstract class Printable{
    def print():String
}
class PrintableByte(b:Byte) extends Printable{
    def print() = b.toString
}
implicit def printableByte(b:Byte) = new PrintableByte(b)

class PrintableArray(a:Array[Byte]) extends Printable {
    def print() = {
        var s:String = ""
        for(i <- 0 until a.length) s += a(i).print()
        s
    }
}
implicit def printableArray(a:Array[Byte]) = new PrintableArray(a)

scala> val a = new Array[Byte](10)
a: Array[Byte] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

scala> a print
res0: String = 0000000000
0
source

Source: https://habr.com/ru/post/1752655/


All Articles