简体   繁体   English

咖喱应用于特质伴侣对象

[英]Curried apply in trait companion object

Two questions: 两个问题:

1) Why am I unable to have these two apply methods in the BaseTrait companion object when the apply functions are curried (note, it works when they are un-curried, with two arguments)? 1)当apply函数被咖喱化时,为什么我不能在BaseTrait伴随对象中拥有这两个apply方法(注意,当它们被非咖喱化时,带有两个参数,它可以工作)?

2) How can I achieve this functionality: multiple apply methods that are curried? 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]
}

It compiles fine, but throws a runtime error: 它可以正常编译,但是会引发运行时错误:

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) }

If you reverse the order of the current arguments, such that they differ in the first argument, then the apply method can be invoked successfully. 如果您颠倒当前参数的顺序,以使它们在第一个参数中不同,则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

As mentioned in the comment, this appears to be a corner case in the language . 如评论中所述, 这似乎是该语言的一个极端案例 In the referenced issue, which was closed with a Wont-Fix status, the following simpler code also exhibits the same ambiguous reference issue. 在以“ Wont-Fix”状态关闭的引用问题中,以下更简单的代码也表现出相同的歧义引用问题。

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

According to Scala language creator Martin Odersky, 根据Scala语言创建者Martin Odersky的说法,

"I just wrote above that there is no attempt to do such a thing in the spec. I challenge you to give a set of complete and decidable rules to do this." “我只是在上面写道,规范中没有尝试做这样的事情。我向您挑战,请您提供一套完整且可确定的规则来做到这一点。”

So it appears that due to the difficulty of implementing the necessary checks, it is not possible prevent these methods from compiling even though they cannot be subsequently referenced. 因此看来,由于难以实施必要的检查,因此即使无法随后引用这些方法,也无法阻止这些方法的编译。

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

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