为什么第一种方法编译失败?
I've opened a bug for this issue.
这似乎是隐式搜索中的编译器怪癖。由于您提供了转换Seq[A] => Seq[B] 的convert 方法,因此编译器无法正确对齐类型。这是用Ytyper-debug编译的输出:
| [search #3] start `[U, T](seq: Seq[U])(implicit converter: U => T)Seq[T]` inferring type T, searching for adaptation to pt=A => T (silent: method example in Test) implicits disabled
| [search #3] considering aToB
| |-- { ((a: A) => Conversions.aToB(a)) } : pt=A => ? EXPRmode (silent: method example in Test) implicits disabled
| | |-- ((a: A) => Conversions.aToB(a)) : pt=A => ? EXPRmode (silent: method example in Test) implicits disabled
| | | |-- Conversions.aToB(a) EXPRmode (silent: value $anonfun in Test) implicits disabled
| | | | |-- Conversions.aToB BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value $anonfun in Test) implicits disabled
| | | | | \-> (a: A)B
| | | | |-- a : pt=A BYVALmode-EXPRmode (silent: value $anonfun in Test) implicits disabled
| | | | | \-> A
| | | | \-> B
| | | \-> A => B
| | \-> A => B
| [adapt] aToB adapted to { ((a: A) => Conversions.aToB(a)) } based on pt A => T
| [search #3] solve tvars=?T, tvars.constr= >: B
| solving for (T: ?T)
| [search #3] success inferred value of type A => =?B is SearchResult({
| ((a: A) => Conversions.aToB(a))
| }, TreeTypeSubstituter(List(type T),List(B)))
| solving for (A: ?A)
| solving for (A: ?A)
| solving for (A: ?A)
| solving for (A: ?A)
| [search #3] considering $conforms
| solving for (A: ?A)
| [adapt] $conforms adapted to [A]=> <:<[A,A] based on pt A => T
| [search #3] solve tvars=?T, tvars.constr= >: A
| solving for (T: ?T)
| [search #3] success inferred value of type A => =?A is SearchResult(scala.Predef.$conforms[A], TreeTypeSubstituter(List(type T),List(A)))
似乎搜索#3 正在尝试调整conforms (<:<),它将整个隐式搜索从A => B 带到A => A。如果我使用-Yno-predef 编译,则隐式转换成功:
| | |-- [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] : pt=Seq[B] EXPRmode (silent: method example in Test) implicits disabled
| | | [search #4] start `[U, T](seq: Seq[U])(implicit converter: U => T)Seq[T]`, searching for adaptation to pt=A => B (silent: method example in Test) implicits disabled
| | | [search #4] considering aToB
| | | |-- { ((a: A) => Conversions.aToB(a)) } : pt=A => B EXPRmode (silent: method example in Test) implicits disabled
| | | | |-- ((a: A) => Conversions.aToB(a)) : pt=A => B EXPRmode (silent: method example in Test) implicits disabled
| | | | | |-- Conversions.aToB(a) : pt=B EXPRmode (silent: value $anonfun in Test) implicits disabled
| | | | | | |-- Conversions.aToB BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value $anonfun in Test) implicits disabled
| | | | | | | \-> (a: A)B
| | | | | | |-- a : pt=A BYVALmode-EXPRmode (silent: value $anonfun in Test) implicits disabled
| | | | | | | \-> A
| | | | | | \-> B
| | | | | \-> A => B
| | | | \-> A => B
| | | [adapt] aToB adapted to { ((a: A) => Conversions.aToB(a)) } based on pt A => B
| | | [search #4] success inferred value of type A => B is SearchResult({
| | | ((a: A) => Conversions.aToB(a))
| | | }, )
| | | |-- [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] : pt=Seq[B] EXPRmode (silent: method example in Test) implicits disabled
| | | | \-> Seq[B]
| | | [adapt] [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] adapted to [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] based on pt Seq[B]
| | | \-> Seq[B]
| | [adapt] Seq[A] adapted to [U, T](seq: Seq[U])(implicit converter: U => T)Seq[T] based on pt Seq[B]
| | \-> Seq[B]
| \-> [def example] ()Seq[B]
这是否与类型擦除有关,如果是,如何使用
Functor 有帮助吗?
第二个示例有效,因为您现在明确说明如何使用Functor 类型类将Seq[A] 映射到Seq[B],因此当编译器看到Seq[A] 时,它具有隐式将其转换为Seq[B]:
def example(): Seq[B] = Conversions.functorConvert[Seq, A, B](sa)({
((a: A) => Conversions.aToB(a))
}, Conversions.SeqFunctor);
请注意,您需要从A => B 进行转换,并且需要Functor[Seq] 才能映射所有As 以将它们转换为Bs,这就是它使用conversions.aToB 所做的事情。