In another question, I'm advised to use with
in a place where one normally uses <:
or <:<
. So instead of defining functions in either of the following two ways:
scala> def f[A,C <: Seq[A]](xs: C) = 0
f: [A, C <: scala.collection.immutable.Seq[A]](xs: C)Int
scala> f(List(1))
<console>:54: error: inferred type arguments [Nothing,List[Int]] do not conform to method f's type parameter bounds [A,C <: scala.collection.immutable.Seq[A]]
f(List(1))
^
scala> implicit def f[A,C](xs: C)(implicit ev: C <:< Seq[A]) = new { def foo = 0 }
f: [A, C](xs: C)(implicit ev: <:<[C,scala.collection.immutable.Seq[A]])java.lang.Object{def foo: Int}
scala> List(0) foo
<console>:54: error: Cannot prove that List[Int] <:< scala.collection.immutable.Seq[A].
List(0) foo
^
scala> f(List(0)) foo
res17: Int = 0
One can do:
scala> implicit def f[A,C](xs: C with Seq[A]) = new { def foo = 0 }
f: [A, C](xs: C with scala.collection.immutable.Seq[A])java.lang.Object{def foo: Int}
scala> List(0) foo
res18: Int = 0
My question is: besides the above particular case, when should one use with
instead of <:
or <:<
on the type parameter? Why not always use with
instead? I'm looking for a discussion of the nuances among the alternatives here. Thanks.
The meanings are entirely different. C <: Seq[A]
means that C
is a subtype of Seq[A]
, as you know; xs: C with Seq[A]
doesn't put any bound on C
, but means that xs
should be both a C
and a Seq[A]
. Therefore you should normally use the one you actually mean.
In def f[A,C <: Seq[A]](xs: C)
the problem is that Scala's compiler can't infer A
because it doesn't appear explicitly in the type of arguments. I don't see any reason in principle it couldn't infer A
; it just doesn't currently. Replacing the type with C with Seq[A]
means A
now appears in the type of xs
and allows the compiler to infer A
. So if you really mean the bound, but A
to be inferred, you actually need to write
implicit def f[A,C <: Seq[A]](xs: C with Seq[A])
instead of your third definition, and this is what the answer to the linked question does.
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