4

I was following the technique presented in the accepted answer to this question How to define "type disjunction" (union types)? in order to support type checking for a multiple-type parameter to a method.

The implicit "evidence"

@implicitNotFound(msg="Only String, Array[Byte] and InputStream are supported")
  sealed class Input[T]
  object Input{
    implicit object ByteArrayWitness extends Input[Array[Byte]]
    implicit object StringWitness extends Input[String]
    implicit object InputStreamWitness extends Input[InputStream]
  }

The API method

def foo[T: Input](param: T) =
  param match {
    case x: String => //...
    case x: Array[Byte] => //...
    case x: InputStream => //...
    case _ => throw new UnsupportedOperationException(s"not implemented for type ${param.getClass}")
  }

The Problem

this compiles

foo("test")
foo(Array[Byte](123.toByte))

but this does not (because it's not a concrete InputStream)

foo(new ByteArrayInputStream("abc".getBytes("UTF-8")))

I have to cast it to the exact super type to make it work (this compiles)

foo(new ByteArrayInputStream("abc".getBytes("UTF-8")).asInstanceOf[InputStream])

Is there a way to change

    implicit object InputStreamWitness extends Input[InputStream]

So that it is an evidence for everything that extends InputStream? I have a feeling there is some upper bound <: notation to plug in somewhere, I just really don't know where...

Or is this where the "crazy lambda calculus stuff" from the highest voted answer to the aforementioned question comes to the rescue?

Community
  • 1
  • 1
Eran Medan
  • 44,555
  • 61
  • 184
  • 276

1 Answers1

7

Make Input contra variant in type T like: Input[-T], it means that if A is super type of B, then Input[B] is super type of Input[A] (reverse "inheritance"). In your case it simply means that Input[InputStream] knows how to handle all subclasses input type InputStream (like ByteArrayInputStream)

I really like the explanation on contravariance by Rex Kerr in this question. But there are many others

Community
  • 1
  • 1
4lex1v
  • 21,367
  • 6
  • 52
  • 86