为什么此代码不采用本地范围中定义的隐式函数? 从哪里采取隐含函数?
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))
我的本地范围内的隐式def都没有被接受。 例如,implctestInt给出结果5,我希望它通过将dble视为隐式返回10。
它也没有显示错误。 implctest只返回传入的参数。
答案 0 :(得分:2)
当您要求函数A => A
时,Scala会提供方法定义的隐式提升,例如
implicit def dble(x: Int):Int = x + x
也就是说,它会将其视为函数dble _
。因此,在隐式解析中,这不是立即可用值。
您遇到的问题是 是任何类型的隐式A => A
,定义为Predef.conforms
:
def conforms[A]: <:<[A, A] // where <:< is a sub class of A => A
这是有用且必要的,因为每当您想要A => B
和A
的视图恰好是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)
。
答案 1 :(得分:1)
如果你要重写你的暗示:
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)
然后您将立即看到此行为的原因。现在你遇到了含糊不清的隐含值的问题:
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"))
^
这通常告诉您Predef
已经定义了隐式函数T => T
,因此它与您的定义冲突。
我建议您不要将Function
等常规类型用作隐式参数。只需为此创建自己的类型。就像在这个例子中一样:
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))