简体   繁体   中英

Union type with upper bound

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM