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

时间:2012-04-24 08:42:44

标签: 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应该向右扩展的基础的声明。 怎么办呢?

4 个答案:

答案 0 :(得分:5)

你做不到。 Function2 [T1,T2,R] 声明抽象方法 apply(t1:T1,t2:T2):R ,所以如果你想混入 Function2 ,您必须实现此arity-2 apply 方法,该方法的签名与您要使用的curried版本不同。

答案 1 :(得分:0)

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

第一个肯定是可能的。请注意,curried函数是返回函数的函数。因此f(x: Int)(y: Int)实际上是Function1,而不是Function2

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

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

你当然可以创建一个实现这个目的的类:

scala> object Foo extends (Int => Int => Int) {
     |   def apply(x: Int) = {(y: Int) => x + y}
     | }
defined module Foo

scala> Foo(1)(2)
res1: Int = 3

不幸的是,我不知道有任何方法可以隐藏第二个参数列表。

答案 2 :(得分:0)

您可以使用隐式转换,而不是扩展(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)

测试:

val foo = new Foo(_ * 10 + _)
foo(4) //error since no implicit Int yet
{
  implicit val impint = 5
  foo(4)  //45
}  
def takesF2(f: (Int, Int) => Int) = f(1, 2)
takesF2(foo)  //12 - works as normal Function2

答案 3 :(得分:0)

一个问题是: 为什么你需要将该对象Foo传递给“其中一个(Int,Int)=&gt; Int是预期的”?

我认为对象Foo应该有一些更特殊的功能,除了作为一个函数之外还会增强它?

在这里分开两个问题似乎更好: a)函数(Int)(隐式Int)=&gt;诠释 和 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)=&gt; Int“,其中(Int,Int)=&gt; Int预期”可能不起作用,因为这些类型不相同。至少当你试图将它放入

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

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