简体   繁体   English

如何将类声明为具有隐式参数的扩展函数

[英]How to declare a class as extending a function with implicit parameters

I would like to define a function that takes one explicit and one implicit parameter, like so: 我想定义一个采用一个显式参数和一个隐式参数的函数,如下所示:

def foo(a: Int)(implicit b: Int) : Int

but as a class or object, like so 但作为一个类或对象,像这样

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

so that the function can be called like this: 这样就可以像下面这样调用该函数:

implicit val b = 2
val g = Foo(1)

I fail to get the declaration of the base from which class Foo should extend right. 我无法获得Foo类应该从其正确扩展的基础的声明。 How can this be done? 如何才能做到这一点?

You cannot. 你不能。 Function2[T1, T2, R] declares the abstract method apply(t1: T1, t2: T2): R , so if you want to mix in Function2 , you have to implement this arity-2 apply method, which has a different signature than the curried version you would like to use. Function2 [T1,T2,R]声明了抽象方法apply(t1:T1,t2:T2):R ,因此,如果要混入Function2 ,则必须实现此arity-2 apply方法,该方法具有不同的签名而不是您要使用的咖喱版本。

So there are two parts to this question - firstly, how does one create an object that implements a function with a curried parameter list. 因此,此问题分为两部分-首先,如何创建一个使用咖喱参数列表实现函数的对象。 And then, how does one make one of those parameter lists implicit. 然后,如何使这些参数列表之一成为隐式。

The first of those is definitely possible. 首先肯定是有可能的。 Note that a curried function is a function that returns a function. 注意,咖喱函数是返回函数的函数。 So f(x: Int)(y: Int) is actually a Function1 , not a Function2 : 所以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>

And you can certainly create a class that implements this: 您当然可以创建一个实现此目的的类:

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

Unfortunately, I'm not aware of any way to make the second parameter list implicit. 不幸的是,我不知道有什么方法可以使第二个参数列表隐式化。

Rather than extending (Int, Int) => Int you could use an implicit conversion: 除了扩展(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)

Test: 测试:

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

A question is: Why do you need necessarily to pass that object Foo to "where an (Int,Int) => Int is expected" ? 一个问题是:为什么您必须将那个对象Foo传递给“期望(Int,Int)=> Int的地方”?

I suppose that object Foo shall have some more special features which does exhance it beyond being a function? 我想对象Foo应该具有更多特殊功能,这些功能除了可以作为功能外还可以发挥作用吗?

It seems better to separate two concerns here: a) The function (Int)(implicit Int) => Int and b) the object 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

You may consider 'foo' a "companion function" if you like ... 如果愿意,您可以将'foo'视为“伴随功能” ...

Beside that: I suppose trying to apply an (Int)(implicit Int)=>Int "where an (Int,Int) => Int is expected" may not work, as these types are not identical. 除此之外:我想尝试应用(Int)(隐式Int)=> Int“其中(Int,Int)=> Int预期为Int”可能不起作用,因为这些类型不相同。 At least when you try to put that into a 至少当您尝试将其放入

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

The method bar would call its parameter f with two arguments anyway, as it expects it to take two, and cannot assume that the provided function in f is indeed able to work with implicits. 方法栏无论如何都将使用两个参数调用其参数f,因为它希望它接受两个参数,并且不能假定f中提供的函数确实能够使用隐式函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM