1

为什么这段代码不采用本地范围内定义的隐式函数?这从哪里获取隐式函数?

def implctest[T](a: T)(implicit b:T=>T):T = {b apply a}
class Testimplcl(val a:Int){
    override def toString() = "value of the 'a' is = "+a
}
implicit def dble(x: Int):Int = {x + x}
implicit def stringer(x: String):String = {x+" no not a pity"}
implicit def myclass(x: Testimplcl):Testimplcl = new Testimplcl(x.a +1)

implctest[String]("oh what a pity")
implctest[Int](5)
implctest[Testimplcl](new Testimplcl(4))

我在本地范围内的任何隐式定义都没有被纳入。例如,implctestInt 给出结果 5,我希望它通过将 dble 视为隐式返回 10。

它也没有显示错误。implctest 只返回传入的参数。

4

2 回答 2

2

当你请求一个函数A => A时,Scala 提供了一个方法定义的隐式提升,例如

implicit def dble(x: Int):Int = x + x

也就是说,它将把它当作一个函数dble _。所以在隐式解析中,这不是一个立即可用的值。

您遇到的问题是任何类型都有一个隐式定义为:A => APredef.conforms

 def conforms[A]: <:<[A, A]   // where <:< is a sub class of A => A

这是有用且必要的,因为无论何时您想要查看A => BA恰好是B,这样的“转换”都是自动可用的。

看,直接功能:

implicit val dble = (x: Int) => x + x

您会看到冲突:

implicitly[Int => Int]   // look for an implicit conversion of that type

<console>:49: error: ambiguous implicit values:
 both method conforms in object Predef of type [A]=> <:<[A,A]
 and value dble of type => Int => Int
 match expected type Int => Int
              implicitly[Int => Int]
                        ^

所以,简而言之,要求定制是不好的A => A。如果您真的需要这样的东西,请使用自定义类型类,例如Foo[A] extends (A => A).

于 2013-06-09T18:33:02.433 回答
1

If you will rewrite your implicits like ths:

implicit val dble = (x: Int) => x + x
implicit val stringer = (x: String) => x + " no not a pity"
implicit val myclass = (x: Testimplcl) => new Testimplcl(x.a +1)

then you will immediately see the reason for this behavior. Now you have the problem with ambiguous implicit values:

scala: ambiguous implicit values:
  both method conforms in object Predef of type [A]=> <:<[A,A]
and value stringer in object ReflectionTest of type => String => String
match expected type String => String
println(implctest[String]("oh what a pity"))
                  ^

This generally tells you that Predef already defined an implicit function T => T, so it conflicts with your definitions.

I will recommend you not to use such general types as Function as implicit parameters. Just create your own type for this. Like in this example:

trait MyTransformer[T] extends (T => T)

object MyTransformer {
  def apply[T](fn: T => T) = new MyTransformer[T] {
    def apply(v: T) = fn(v)
  }
}

def implctest[T: MyTransformer](a: T): T =
  implicitly[MyTransformer[T]] apply a


class Testimplcl(val a:Int){
  override def toString() = "value of the 'a' is = "+a
}

implicit val dble = MyTransformer((x: Int) => x + x)
implicit val stringer = MyTransformer((x: String) => x + " no not a pity")
implicit val myclass = MyTransformer((x: Testimplcl) => new Testimplcl(x.a +1))
于 2013-06-09T18:31:57.217 回答