高阶函数映射中不需要的隐式参数解析

时间:2013-02-04 14:19:56

标签: scala implicit higher-order-functions

我在尝试map使用Option类型的隐式参数定义的某些方法时遇到问题。

假设我定义了一个自定义class和一个trait,其中上述方法在class上运行

class MyClass

trait Processor {

  def stringy(implicit arg: MyClass) = arg.toString

  def lengthy(implicit arg: MyClass) = arg.toString.length

  def inty(implicit arg: MyClass) = arg.toString.map(_.toInt).sum

}

然后我用一些测试创建一个实现

object TestProcessing extends Processor {

  //Here everything works fine, the argument is passed explicitly    
  def test() {
    val my = new MyClass

    val res = List(stringy(my), lengthy(my), inty(my))

    println(res.mkString("\n"))
  }

  //Still everything ok, the argument is passed implicitly    
  def testImplicit() {
    implicit val my = new MyClass

    val res = List(stringy, lengthy, inty)

    println(res.mkString("\n"))
  }

  object Mapper {
    //class wrapped in an Option
    val optional = Some(new MyClass)

    //trying to factor out common code
    def optionally[T](processFunction: MyClass => T): Option[T] = optional map processFunction

    //now the specific processing methods that should work on the optional value
    def s: Option[String] = optionally(stringy)
    def l: Option[Int] = optionally(lengthy)
    def i: Option[Int] = optionally(inty)

    /*
     * Here the compiler complains that
     *
     *<console>:40: error: could not find implicit value for parameter arg: MyClass
     *                def s: Option[String] = optionally(stringy)
     *                                                   ^
     *<console>:41: error: could not find implicit value for parameter arg: MyClass
     *                def l: Option[Int] = optionally(lengthy)
     *                                                ^
     *<console>:42: error: could not find implicit value for parameter arg: MyClass
     *                def i: Option[Int] = optionally(inty)
     *                                                ^
     */    
  }


}

虽然optionally被设想为显式地将可选值显式传递给它的参数函数,但是当我在实际函数上使用它时,编译器需要一个隐式定义。

我有两种可能的解决方案,两者都不令人满意:

  1. 将隐式参数传递给optionally,如

    optionally(implicit my => stringy)

  2. 避免将特定函数的参数定义为implicit,如

    def stringy(arg: MyClass)

  3. 每个解决方案都无法实现可读性和可用性的目标。

    还有第三种方法吗?

1 个答案:

答案 0 :(得分:1)

如果我理解正确,问题是编译器似乎没有意识到你想在这里部分地将方法应用/提升到一个函数(而是“认为”你想要省略隐含参数),所以明确地这样做似乎有效:

def s: Option[String] = optionally(stringy(_))
def l: Option[Int] = optionally(lengthy(_))
def i: Option[Int] = optionally(inty(_))