【问题标题】:How to declare a class as extending a function with implicit parameters如何将类声明为使用隐式参数扩展函数
【发布时间】:2012-05-04 21:21:10
【问题描述】:

我想定义一个带有一个显式和一个隐式参数的函数,如下所示:

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 应该正确扩展的基的声明。 如何做到这一点?

【问题讨论】:

  • 为什么,在这个例子中,你需要“extends ((Int,Int) => Int)”?没有编译也很好。
  • 这样我就可以传递一个 Foo ,其中需要一个 (Int,Int) => Int
  • 对,这就是我说“在这个例子中”的原因
  • @virtualeyes 嗯,好的。 :-) 你知道例子是怎么回事。

标签: function scala implicit


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    所以这个问题有两个部分——首先,如何创建一个对象来实现一个带有柯里化参数列表的函数。然后,如何使这些参数列表之一隐含。

    其中第一个绝对是可能的。请注意,柯里化函数是返回函数的函数。所以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
    

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 顺便说一句,我尝试扩展(Int, Int) =&gt; Int,但问题是def apply(a: A, b: B): Cdef apply(a: A)(implicit b: B): C 在字节码方面最终是相同的,所以两者兼有是非法的。
      【解决方案4】:

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

      我认为对象 Foo 应该具有一些更特殊的功能,这些功能确实可以将其扩展为一个函数?

      在这里分开两个问题似乎更好: a) 函数 (Int)(implicit 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)(implicit Int)=>Int “其中预期 (Int,Int) => Int”可能不起作用,因为这些类型并不相同。至少当您尝试将其放入

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

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

      【讨论】:

        猜你喜欢
        • 2011-10-22
        • 2019-02-10
        • 1970-01-01
        • 2014-04-23
        • 1970-01-01
        • 1970-01-01
        • 2019-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多