Scala隐式函数参数化

时间:2013-06-09 18:14:44

标签: function scala implicit parameterized

为什么此代码不采用本地范围中定义的隐式函数? 从哪里采取隐含函数?

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只返回传入的参数。

2 个答案:

答案 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 => 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)

答案 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))