2011-05-09 43 views
2

由于这个问题说,我想以下(不编译):如何隐式地将适当的应用方法的对象转换为函数?

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) } 
    } 

但是,编译器抱怨“在结构细化参数类型可能不指的是在精化“”之外定义的抽象类型。

编辑:

由于让 - 菲利普·佩莱的答案,我不得不提到我不能让O分别Function[Int,Boolean]延伸Function[A,B]

回答

3

如果你有没有想过它和代码实际上是在你的手中,你也可以简单地做:

val f = O apply _ 

或者,把结构类型明确到F,可以说:

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

如果“val f = O apply _”在上下文中对你有用,那么这就是要走的路。但是这不是对你的问题的回答,而是作为避免回答它的一种方式......并且这不是更糟糕的。 – 2011-05-09 11:11:59

+0

不错,'1至10过滤器(O apply _)'适用于我,虽然_Miles_答案更复杂,但我不能更改'对象O'的代码。 – 2011-05-09 11:17:19

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) 
+0

您确定要编译? – 2011-05-09 09:43:23

+0

对不起,你是对的。经常发现,声明一个单独的类而不是结构隐式解决了这个问题,但在这种情况下不能解决问题。我建议的唯一的事情就是使隐含的非参数化 – 2011-05-09 10:27:00

+0

编辑完成后,编译。你是否也可以使它成为通用的,所以我不必为每个'A => B'重写隐式转换? – 2011-05-09 10:27:37

0

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

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

对不起,我应该提到,我知道,但这意味着我必须更改客户端代码,现在不可能。 – 2011-05-09 09:48:40

6

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

但是,我们可以通过消除有问题的情况来逼近期望的结果,以支持内部类型参数,并且类型约束与应用该方法的任何点处的类型约束强制它等于原始参数类型A.

要做到这一点,你必须修改你试图从结构上捕获方法的签名的一般形式(注意:伪如下),

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 
+0

英里,非常成熟!你的方法意味着我必须改变'O'的代码,与_Jean-Philippe Pellet_的答案一样的问题,但我已经学到了非常聪明的东西!谢谢!我一般喜欢你的答案。可惜没有双重赞扬。 – 2011-05-09 11:15:40

相关问题