lam*_*das 19 scala ambiguity implicit-conversion
我一直以为我理解scala implicits直到最近才遇到奇怪的问题.
在我的应用程序中,我有几个域类
case class Foo(baz: String)
case class Bar(baz: String)
还有一个能够从字符串构造域对象的类.它可以被子类化以进行真正的反序列化并不重要.
class Reads[A] {
  def read(s: String): A = throw new Exception("not implemented")
}
接下来,有隐式反序列化器
implicit val fooReads = new Reads[Foo]
implicit val barReads = new Reads[Bar]
以及将字符串转换为域类之一的帮助器
def convert[A](s: String)(implicit reads: Reads[A]): A = reads.read(s)
不幸的是,在尝试使用它时
def f(s: String): Foo = convert(s)
我得到编译错误
error: ambiguous implicit values:
 both value fooReads of type => Reads[Foo]
 and value barReads of type => Reads[Bar]
 match expected type Reads[A]
       def f(s: String): Foo = convert(s)
                                      ^
对我而言,代码似乎很简单.Reads[Foo]并且Reads[Bar]是一个完全不同的类型,它有什么含糊之处?
真正的代码更加复杂和使用,play.api.libs.json但这个简化版本足以重现错误.
whe*_*ies 13
您在示例中遇到的模糊性是您没有告诉Scalac您想要使用哪一个.您需要替换代码
def f(s: String): Foo = convert[Foo](s)
为了弄清楚要使用哪一个.它无法从返回类型推断出来f.它需要在这里明确.
回应评论
让我在这里扮演魔鬼的拥护者.
trait Foo
case class Bar(s: String) extends Foo
case class Baz(s: String) extends Foo
def f(s: String): Foo = convert(s)
假设有两个Bar和Baz?我确定那里有更多恶魔般的角落案件,但是这个案件跳出来了.
小智 8
问题是您正在制作通用类型A不变量.相反,这应该是协变的.所以这应该实现如下
case class Foo(baz: String)
case class Bar(baz: String)
// This `+` ? is the only difference  
class Reads[+A] {
  def read(s: String): A = throw new Exception("not implemented")
}
implicit val fooReads = new Reads[Foo]
implicit val barReads = new Reads[Bar]
def convert[A](s: String)(implicit reads: Reads[A]): A = reads.read(s)
def f(s: String): Foo = convert(s)
有关更多信息,请参阅http://docs.scala-lang.org/tutorials/tour/variances.html.
| 归档时间: | 
 | 
| 查看次数: | 10698 次 | 
| 最近记录: |