如何使用适当的apply方法将对象隐式转换为函数?

时间:2011-05-09 09:24:34

标签: scala

正如问题所说我正在尝试以下(不编译):

  object O {
    def apply(i: Int): Boolean = i % 2 == 0
  }
  val f: Int => Boolean = O

所以我尝试了这个:

  implicit def apply2Fct[A,B](applier: { def apply(a: A): B }) = {
    new Function[A,B] { def apply(a: A): B = applier(a) }
  }

但编译器抱怨“结构细化中的参数类型可能不会引用在该细化之外定义的抽象类型”

编辑:

由于 Jean-Philippe Pellet 的答案,我不得不提及O分别Function[A,B] Function[Int,Boolean] {/ 1}}。

4 个答案:

答案 0 :(得分:6)

由于Gilles在ticket #967上提供的原因,您无法直接执行此操作。有问题的构造是在结构类型中的方法定义的裸参数位置中出现外部定义的类型参数A.

但是,我们可以通过消除有问题的事件来取代所需的结果,而有利于内部类型参数加上类型约束,迫使它在应用该方法的任何点处等于原始参数类型A. / p>

要做到这一点,你必须修改你试图从结构上捕获的方法的签名的一般形式(nb.pseudocode follow),

def method(x : <<your arg type>>) : <<your result type>>

def method[T](x : T)(implicit ev : T =:= <<your arg type>>) : <<your result type>>

对于您的特定情况,我们需要以下内容,

object O {
  def apply[T](i : T)(implicit ev : T =:= Int) : Boolean = i % 2 == 0
}

implicit def apply2Fct[A,B](applier: { def apply[T](a: T)(implicit ev : T =:= A): B }) = {
  new Function[A,B] { def apply(a: A): B = applier(a) }
}

示例REPL会话,

scala> implicit def apply2Fct[A,B](applier: { def apply[T](a: T)(implicit ev : T =:= A): B }) = {
     | new Function[A,B] { def apply(a: A): B = applier(a) }
     | }
apply2Fct: [A, B](applier: AnyRef{def apply[T](a: T)(implicit ev: =:=[T,A]): B})java.lang.Object with (A) => B

scala> object O {
     | def apply[T](i : T)(implicit ev : T =:= Int) : Boolean = i % 2 == 0
     | }
defined module O

scala> O(23)
res0: Boolean = false

scala> O(24)
res1: Boolean = true

scala> val f: Int => Boolean = O
f: (Int) => Boolean = <function1>                                                                                                                                                                                                              

scala> f(23)                                                                                                                                                                                                                                   
res2: Boolean = false                                                                                                                                                                                                                          

scala> f(24)                                                                                                                                                                                                                                   
res3: Boolean = true  

答案 1 :(得分:3)

如果您没有考虑过这个问题并且代码实际上在您手中,您可能也会这么做:

val f = O apply _

或者,将结构类型明确地赋予f,可以说:

val f: { def apply(i: Int): Boolean } = O

答案 2 :(得分:0)

您是否尝试过将隐式转换设为非参数化(不太好,我意识到了)?

class ApplyIsF1( self : { def apply(a : Int) : Boolean }) extends (Int => Boolean) {
  def apply(a : Int) = self apply a
}

implicit def applyIsF1(self : { def apply(a : Int) : Boolean }) = new ApplyIsF1(self)

答案 3 :(得分:0)

您应该明确告诉编译器O是一个函数:

object O extends (Int => Boolean) {
  def apply(i: Int): Boolean = i % 2 == 0
}