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

发布于 2024-11-06 13:18:29 字数 529 浏览 1 评论 0原文

正如问题所说,我正在尝试以下操作(无法编译):

  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] 分别是函数[Int,Boolean]

As the question says I am trying the following (does not compile):

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

So I tried this:

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

But the compiler complains about "Parameter type in structural refinement may not refer to an abstract type defined outside that refinement".

EDIT :

Due to the answer of Jean-Philippe Pellet I have to mention that I can´t let O extend Function[A,B] respectively Function[Int,Boolean].

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浴红衣 2024-11-13 13:18:29

您不能直接执行此操作,原因是 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  

You can't do this directly for the reasons that Gilles gives on ticket #967. The problematic construct is the occurrence of the externally defined type parameter A in a bare argument position on a method definition within the structural type.

However, we can approximate the desired result by eliminating the problematic occurrence in favour of an internal type parameter coupled with a type constraint forcing it to be equal to the original argument type A at any point at which the method is applied.

To do this you have to modify the general form of the signatures of the methods you're trying to capture structurally from (nb. pseudocode follows),

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

to

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

For your particular case we would need something like the following,

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

Sample REPL session,

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  
染火枫林 2024-11-13 13:18:29

如果您没有考虑过并且代码实际上在您手中,您也可以简单地这样做:

val f = O apply _

或者,将结构类型显式地放入 f,可以说:

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

In case you haven’t thought about it and the code is actually in your hands, you might also simply do:

val f = O apply _

Or, putting the structural type explicitly to f, one could say:

val f: { def apply(i: Int): Boolean } = O
上课铃就是安魂曲 2024-11-13 13:18:29

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

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

You should explicitly tell the compiler that O is a function:

object O extends (Int => Boolean) {
  def apply(i: Int): Boolean = i % 2 == 0
}
煮酒 2024-11-13 13:18:29

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

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)

Have you tried making the implicit conversion non-parameterized (not great, I realize)?

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文