Function 如何将类声明为使用隐式参数扩展函数

Function 如何将类声明为使用隐式参数扩展函数,function,scala,implicit,Function,Scala,Implicit,我想定义一个函数,它接受一个显式参数和一个隐式参数,如下所示: def foo(a: Int)(implicit b: Int) : Int 但作为一个类或对象,就像这样 object Foo extends ((Int,Int) => Int) { def apply(a: Int)(implicit b: Int) : Int = { ... } } 这样就可以像这样调用函数: implicit val b = 2 val g = Foo(1) 我无法获得类Foo应该从中正确

我想定义一个函数,它接受一个显式参数和一个隐式参数,如下所示:

def foo(a: Int)(implicit b: Int) : Int
但作为一个类或对象,就像这样

object Foo extends ((Int,Int) => Int) {
  def apply(a: Int)(implicit b: Int) : Int = { ... }
}
这样就可以像这样调用函数:

implicit val b = 2
val g = Foo(1)
我无法获得类
Foo
应该从中正确扩展的基的声明。
如何做到这一点?

你不能。Function2[T1,T2,R]声明了抽象方法apply(T1:T1,T2:T2):R,因此如果您想混合使用Function2,您必须实现这个arity-2 apply方法,它的签名与您想要使用的当前版本不同。

因此这个问题有两个部分-首先,如何创建一个使用当前参数列表实现函数的对象。然后,如何使这些参数列表中的一个隐式

第一个是绝对可能的。请注意,curried函数是返回函数的函数。因此
f(x:Int)(y:Int)
实际上是
函数1
,而不是
函数2

scala> def f(x: Int)(y: Int) = x + y
f: (x: Int)(y: Int)Int

scala> f _
res0: Int => Int => Int = <function1>

不幸的是,我不知道有什么方法可以使第二个参数列表隐式化。

您可以使用隐式转换,而不是扩展
(Int,Int)=>Int

class Foo(f: (Int, Int) => Int) {
  def apply(a: Int)(implicit b: Int) : Int = f(a, b)
}

implicit def Foo_to_Function2(foo: Foo) = (x: Int, y: Int) => foo(x)(y)
测试:

问题是: 为什么您需要将该对象Foo传递给“需要(Int,Int)=>Int的地方”

我想对象Foo应该有一些更特殊的特性,这些特性不仅仅是一个函数

这里最好将两个问题分开: a) 函数(Int)(隐式Int)=>Int 及 b) 对象Foo

object Foo {
  def apply(a: Int, b: Int) : Int = { ... }
}

def foo(a: Int)(implicit b: Int) : Int = Foo(a, b)

implicit val m:Int = 42

foo(5)  // --> res1: Int = 47
如果你喜欢……,你可以考虑“Foo”一个“同伴函数”。 除此之外:我假设尝试应用(Int)(隐式Int)=>Int“其中(Int,Int)=>Int是预期的”可能不起作用,因为这些类型不相同。至少当你试着把它放到一个

def bar(f:(Int,Int)=>Int) = ....

方法栏无论如何都会使用两个参数调用其参数f,因为它希望它使用两个参数,并且不能假设f中提供的函数确实能够使用隐式函数。

在本例中,为什么需要“extends((Int,Int)=>Int)”?编译很好,没有。所以我可以传递一个Foo,其中(Int,Int)=>Int是expectedright,这就是为什么我说,“在这个例子中”@virtualeyes,嗯,好的.:-)你知道例子是怎样的。顺便说一句,我试着扩展
(Int,Int)=>Int
,但问题是
def-apply(a:a,b:b):C
def-apply(a:a)(隐式b:b):C
在字节码术语中是一样的,所以两者都是非法的。
object Foo {
  def apply(a: Int, b: Int) : Int = { ... }
}

def foo(a: Int)(implicit b: Int) : Int = Foo(a, b)

implicit val m:Int = 42

foo(5)  // --> res1: Int = 47
def bar(f:(Int,Int)=>Int) = ....