Curried适用于特质伴侣对象

时间:2017-12-16 01:54:35

标签: scala

两个问题:

1)当apply函数被咖喱时,为什么我无法在BaseTrait伴随对象中使用这两个apply方法(请注意,它们在没有咖喱时会起作用,有两个参数)?

2)如何实现此功能:多个应用方法??

trait BaseTrait[T, U] {
  def name: String
  def tryMe(record: T): Option[U]
}

object BaseTrait {
  // can't have both apply methods when curried
  def apply[T](s: String)(f: T => Option[Long]): LongTrait[T] =
    new LongTrait[T] {
      override val name: String = s
      override def tryMe(record: T): Option[Long] = f(record)
    }

  def apply[T](s: String)(f: T => Option[Boolean]): BooleanTrait[T] =
    new BooleanTrait[T] {
      override val name: String = s
      override def tryMe(record: T): Option[Boolean] = f(record)
    }
}

trait LongTrait[T] extends BaseTrait[T, Long] {
  override def tryMe(record: T): Option[Long]
}

trait BooleanTrait[T] extends BaseTrait[T, Boolean] {
  override def tryMe(record: T): Option[Boolean]
}

它编译得很好,但会引发运行时错误:

scala> BaseTrait("test") { s: String => Option(s.toBoolean) }

<console>:13: error: ambiguous reference to overloaded definition,
both method apply in object BaseTrait of type [T](s: String)(f: T => 
Option[Boolean])BooleanTrait[T]
and  method apply in object BaseTrait of type [T](s: String)(f: T => 
Option[Long])LongTrait[T]
match argument types (String)
   BaseTrait("test") { s: String => Option(s.toBoolean) }

1 个答案:

答案 0 :(得分:3)

如果颠倒当前参数的顺序,使它们在第一个参数中不同,则可以成功调用apply方法。

object BaseTrait {
    // can't have both apply methods when curried
    def apply[T](f: T => Option[Long])(s: String): LongTrait[T] =
      new LongTrait[T] {
        override val name: String = s
        override def tryMe(record: T): Option[Long] = f(record)
      }

    def apply[T](f: T => Option[Boolean])(s:String): BooleanTrait[T] =
      new BooleanTrait[T] {
        override val name: String = s
        override def tryMe(record: T): Option[Boolean] = f(record)
      }
  } 

BaseTrait { s:String => Option(s.toBoolean) }("test") 
res58: BooleanTrait[String] = ammonite.$sess.cmd57$BaseTrait$$anon$2@e39317d

如评论中所述,this appears to be a corner case in the language。在引用的问题中,以Wont-Fix状态关闭,以下更简单的代码也表现出相同的模糊引用问题。

object Foo {
  def bar(i: Int) = println(i)
  def bar(i: Int) (f: Float) = println(i*f)
}

根据Scala语言创建者Martin Odersky所说,

&#34;我刚刚在上面写道,没有尝试在规范中做这样的事情。我要求你提供一套完整且可判定的规则来实现这一目标。&#34;

因此,由于难以实施必要的检查,即使无法随后引用这些方法,也无法阻止这些方法的编制。