3

I'm trying to find the place in the language specification that should have informed me that these kind of implicit conversions don't work:

scala> implicit def listToAlternativeList[F,T](xs: List[F])(implicit conv: (F) => T) = xs map conv listToAlternativeList: [F,T](xs: List[F])(implicit conv: (F) => T)List[T] scala> implicit def int2string(i: Int) = i.toString int2string: (i: Int)java.lang.String scala> val l = List(1, 2, 3) l: List[Int] = List(1, 2, 3) scala> val l2: List[String] = listToAlternativeList[Int,String](l) l2: List[String] = List(1, 2, 3) scala> val l2: List[String] = listToAlternativeList(l) l2: List[String] = List(1, 2, 3) scala> val l2: List[String] = l <console>:10: error: type mismatch; found : List[Int] required: scala.List[String] val l2: List[String] = l ^ 

Basically, all I want is to assign a List of a certain type to a variable that is declared to be of another type and get the implicit conversions kicking in. It obviously doesn't work. I can come up with ways to work around that, but I just hate it that I don't understand the general rule at work here. Anyone?

1 Answer 1

4

It is possible for an implicit view to to itself require an implicit parameter. For example:

scala> implicit def listToStringList[A](as: List[A])(implicit f: A => String) = as map f listToStringList: [A](as: List[A])(implicit f: (A) => String)List[String] scala> implicit def i2s(i: Int) = i.toString i2s: (i: Int)java.lang.String scala> val l = List(1) l: List[Int] = List(1) scala> l: List[String] res0: List[String] = List(1) 

What happens in your case? Well, let's look behind the curtains with scala -Ytyper-debug -Xlog-implicits with this script:

implicit def listToList[A, B](as: List[A])(implicit f: A => B): List[B] = as map f implicit def i2s(i: Int): String = i.toString val l = List(1) l: List[String] 

The compiler then explains:

typing (l: List[String]), pt = ?, undetparams = List(), implicits-enabled = true, silent = true typing List[String], pt = ?, undetparams = List(), implicits-enabled = true, silent = true typing scala.package, pt = ?, undetparams = List(), implicits-enabled = true, silent = true typing scala, pt = ?, undetparams = List(), implicits-enabled = true, silent = true typed scala:type with underlying package scala, undetparams = List(), pt = ? adapted scala:package scala to ?, List() typed scala.package:type with underlying object package, undetparams = List(), pt = ? adapted scala.package:object package to ?, List() typing String, pt = ?, undetparams = List(), implicits-enabled = true, silent = true typed scala.this.Predef.String:String, undetparams = List(), pt = ? adapted scala.this.Predef.String:String to ?, List() typed List[String]:List[String], undetparams = List(), pt = ? adapted List[String]:List[String] to ?, List() typing l, pt = List[String], undetparams = List(), implicits-enabled = true, silent = true typed $anon.this.l:=> List[Int], undetparams = List(), pt = List[String] Beginning implicit search for $anon.this.l expecting (List[Int]) => List[String] looking for a view begin implicit search: ($anon.this.l,(List[Int]) => List[String],true,List()) typed impl for (List[Int]) => List[String]? listToList:(as: List[?])(implicit f: (?) => ?)List[?] orig info= [A,B](as: List[A])(implicit f: (A) => B)List[B]/List()/true/true/this.type/true typedImplicit0 typing$anon.this.listToList with wildpt = (List[Int]) => List[String] from implicit listToList:[A,B](as: List[A])(implicit f: (A) => B)List[B] typing $anon.this.listToList, pt = ?, undetparams = List(), implicits-enabled = false, silent = false typing $anon.this, pt = ?, undetparams = List(), implicits-enabled = false, silent = false typed $anon.this:this.type with underlying java.lang.Object{}, undetparams = List(), pt = ? adapted $anon.this:java.lang.Object{} to ?, List() typed $anon.this.listToList:[A,B](as: List[A])(implicit f: (A) => B)List[B], undetparams = List(), pt = ? adapted $anon.this.listToList:[A,B](as: List[A])(implicit f: (A) => B)List[B] to ?, List(type A, type B) typing <argument>, pt = List[?], undetparams = List(), implicits-enabled = false, silent = false typed <argument>:List[Int], undetparams = List(), pt = List[?] adapted <argument>:List[Int] to List[?], List() typing <argument>, pt = List[Int], undetparams = List(), implicits-enabled = false, silent = false typed <argument>:List[Int], undetparams = List(), pt = List[Int] adapted <argument>:List[Int] to List[Int], List() typed implicit $anon.this.listToList[Int, B](<argument>):(implicit f: (Int) => B)List[B], pt = (List[Int]) => List[String] adapted implicit method listToList:(as: List[Int])(implicit f: (Int) => B)List[B] to (List[Int]) => List[String] incompatible: (as: List[Int])(implicit f: (Int) => B)List[B] does not match (List[Int]) => List[String] Implicit search yielded: SearchResult(<empty>, TreeTypeSubstituter(List(),List())) 

I'm not quite sure if this is a bug or feature. But maybe this output will help someone else illuminate the matter further.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.