Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need an explicit evidence type / why does this Scala type bound fail?

Tags:

scala

Below, the first case succeeds and the second fails. Why do I need an explicit evidence type / why does this Scala type bound fail? What's the type inferencer's particular limitation here in solving for A?

scala> implicit def view[A, C](xs: C)(implicit ev: C <:< Iterable[A]) = new { def bar = 0 } 
view: [A, C](xs: C)(implicit ev: <:<[C,scala.collection.immutable.Iterable[A]])java.lang.Object{def bar: Int}

scala> view(List(1)) bar
res37: Int = 0

scala> implicit def view[A, C <: Seq[A]](xs: C) = new { def bar = 0 } 
view: [A, C <: scala.collection.immutable.Seq[A]](xs: C)java.lang.Object{def bar: Int}

scala> view(List(1)) bar
<console>:149: error: inferred type arguments [Nothing,List[Int]] do not conform to method view's type parameter bounds [A,C <: scala.collection.immutable.Seq[A]]
              view(List(1)) bar
              ^
like image 712
Yang Avatar asked Dec 28 '22 09:12

Yang


1 Answers

Type inference unfortunately does not deal well with type parameters (such as C) that are bounded by (types that contain) other type parameters in the same type parameter list (here, A).

The version that encodes the constraint using an implicit argument does not suffer from this restriction since constraints imposed by implicits are solved separately from constraints imposed by type parameter bounds.

You can also avoid the cycle by splitting up the type of xs into the type constructor that abstracts over the collection (CC) and the (proper) type (A) that abstracts over its elements, like so:

scala> implicit def view[A, CC[x] <: Seq[x]](xs: CC[A]) = new { def bar = 0 } 
view: [A, CC[x] <: Seq[x]](xs: CC[A])Object{def bar: Int}

scala> view(List(1)) bar
res0: Int = 0

For more details on types like CC, please see What is a higher kinded type in Scala?

like image 132
Adriaan Moors Avatar answered Jun 01 '23 14:06

Adriaan Moors