In my Scala code, I have an array of Option[T]
, like so:
val items = Array.fill[Option[T]](10)(None)
Now, I want to read a specific item from that array; if it has not been set, I want to have null
. But when I do items(desiredIndex).orNull
, the Scala compiler yells at me:
Error:(32, 34) Cannot prove that Null <:< T.
(items(desiredIndex).orNull).asInstanceOf[T]
I don't fully understand this error. What I do understand is that the compiler cannot infer that null
is indeed a valid value for T
(since it is not known what T
will be). Looking at the implementation, I should supply implicit evidence for the fact that null
is a valid value for T
:
@inline final def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse ev(null)
Now, my question is: how can I supply such evidence? What type is ev
supposed to be, and how can I create a value for it?
By a type bound:
scala> def f[T >: Null : ClassTag]: T = {
| val items = Array.fill[Option[T]](10)(None)
| items(0).orNull }
f: [T >: Null](implicit evidence$1: scala.reflect.ClassTag[T])T
scala> f[String]
res3: String = null
Per Pedro:
scala> def f[T >: Null]: T = Array.fill[Option[T]](10)(None).apply(0).orNull
f: [T >: Null]=> T
While the solution given by som-snytt is simpler and better for this specific case, to answer the questions directly:
What type is ev supposed to be
Null <:< A1
(this is just a different way to write <:<[Null, A1]
).
and how can I create a value for it
For a specific type you don't need to, the compiler will provide this evidence itself (using scala.Predef.$conforms
). But when working with a generic T
, you can just add the same implicit parameter to your method (or, for <:<
specifically, a type bound), and to methods calling it, etc. until you come to a specific type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With