鉴于:
scala> trait Resource[A] { def f: String }
defined trait Resource
scala> case class Foo(x: String)
defined class Foo
Run Code Online (Sandbox Code Playgroud)
然后暗示:
scala> implicit def fooToResource(foo: Foo): Resource[Foo] =
new Resource[Foo] { def f = foo.x }
Run Code Online (Sandbox Code Playgroud)
以下作品:
scala> implicitly[Resource[Foo]](Foo("foo")).f
res2: String = foo
Run Code Online (Sandbox Code Playgroud)
我定义了一个函数:
scala> def f[A](x: A)(implicit ev: Resource[A]): String = ev.f
f: [A](x: A)(implicit ev: Resource[A])String
Run Code Online (Sandbox Code Playgroud)
但是,以下代码无法编译:
scala> f(Foo("foo"))
<console>:17: error: could not find implicit value for parameter ev: Resource[Foo]
f(Foo("foo"))
Run Code Online (Sandbox Code Playgroud)
其次,我尝试过:
scala> f2(Foo("bippy"))
<console>:17: error: could not find implicit value for parameter ev: Resource[Foo]
f2(Foo("bippy"))
^
Run Code Online (Sandbox Code Playgroud)
最后,我试图:
scala> def g(foo: Foo)(implicit ev: Resource[Foo]): String = ev.f
g: (foo: Foo)(implicit ev: Resource[Foo])String
scala> g(Foo("5"))
<console>:17: error: could not find implicit value for parameter ev: Resource[Foo]
g(Foo("5"))
^
Run Code Online (Sandbox Code Playgroud)
但是,它也失败了.我该怎么f办?
好的,Peter Neyens的回答,这不是一个类型类,这是一个隐式转换,你应该避免 - 应该有一些警告,要求你导入scala.language.implicitConversions.
作为补充,这就是为什么第一个implicitly有效:
隐含的只是:
def implicitly[T](implicit ev: T): T = e
Run Code Online (Sandbox Code Playgroud)
在implicitly[T] 不提供参数的情况下编写时,它将T在范围中查找隐式类型并返回它.但是,你用一个参数隐式调用(我相信没有正当理由这样做,所以它只会返回你的参数Foo("foo"),一个实例)Foo.除非您明确声明T应该是Resource [Foo].如果您已经编写了类型归属,例如(Foo("foo"): Resource[Foo]),它将以相同的方式工作.implicitly与此无关.
关键是Foo("foo")不是预期的类型Resource[Foo],而只是一个Foo.编译器会拒绝它,除了此时,您在上面定义的隐式转换启动,并且您的Foo实例转换为Resource[Foo].然后,你可以打电话f.
接下来,你打电话给你f(Foo("foo")).有一个隐含参数,但是这次你不提供它.所以编译器会查找一个(虽然它第一次没有这样做),并且因为没有这样的实例,所以失败了.