Scala: аргументы конструктора, включающие внутренние типы ограниченных типов - PullRequest
1 голос
/ 07 мая 2011

В scala 2.9.0.RC3 я определил черту для парсеров и конкретный пример парсера:

trait Parser {
  type Result
  def parse(s: String): Result
}

class IdParser extends Parser {
  case class Result(s: String)
  def parse(s: String) = new Result(s)
}

Теперь я хотел бы иметь возможность сравнивать проанализированные значения:

class Comparator[P <: Parser](p: P) {
  def compare(s1: String, s2: String) = p.parse(s1) == p.parse(s2)
}

Это прекрасно работает, я могу сделать:

println(new Comparator(new IdParser).compare("a", "b"))

И выдает false , как и ожидалось. К сожалению, отсюда все становится хуже. Чтобы учесть более интересное сравнение, я определяю:

class CustomisableComparator[P <: Parser](p: P, 
      cmp: (P#Result, P#Result) => Boolean = (r1: P#Result, r2: P#Result) => r1 == r2) {
  def compare(s1: String, s2: String) = cmp(p.parse(s1), p.parse(s2))
} 

И попробуйте вызвать его, как и раньше:

println(new CustomisableComparator(new IdParser).compare("a", "b"))

Но тогда:

error: type mismatch;
 found   : (this.Parser#Result, this.Parser#Result) => Boolean
 required: (this.IdParser#Result, this.IdParser#Result) => Boolean
Error occurred in an application involving default arguments.
println(new CustomisableComparator(new IdParser).compare("a", "b"))
        ^

О, хорошо, я бы ожидал, что переменная типа P в CustomisableComparator будет привязана к IdParser, поэтому я не совсем уверен, почему scala считает ее Parser значением по умолчанию. Тогда давайте забудем о значении по умолчанию и предоставим значение явно:

println(new CustomisableComparator(new IdParser, (r1: IdParser#Result, r2: IdParser#Result) => r1 == r2).compare("a", "b"))
error: type mismatch;
 found   : (this.IdParser#Result, this.IdParser#Result) => Boolean
 required: (?#Result, ?#Result) => Boolean

println(new CustomisableComparator(new IdParser, (r1: IdParser#Result, r2: IdParser#Result) => r1 == r2).compare("a", "b"))
                                                                                            ^

Это очень запутанно. Если я не предоставлю значение, компилятор ожидает (this.IdParser#Result, this.IdParser#Result) => Boolean; как только я предоставлю значение этого типа, он ожидает (?#Result, ?#Result) => Boolean. Кто-нибудь может объяснить, что здесь происходит?

1 Ответ

4 голосов
/ 07 мая 2011

Вы просто запрашиваете слишком много выводов типа. Вы, кажется, думаете, что это отменит вас, и это не так.

Оба ваших примера компилируются, если вы укажете тип:

println(new CustomisableComparator[Parser](new IdParser).compare("a", "b"))
println(new CustomisableComparator[IdParser](new IdParser, (r1: IdParser#Result, r2: IdParser#Result) => r1 == r2).compare("a", "b"))

Или вы получите лучший вывод типа в этих ситуациях (он идет слева направо), если вы будете использовать дополнительные списки параметров в стратегических местах.

class CustomisableComparator2[P <: Parser](p: P)(cmp: (P#Result, P#Result) => Boolean = ((x: P#Result, y: P#Result) => x == y)) {
  def compare(s1: String, s2: String) = cmp(p.parse(s1), p.parse(s2))
}
// type parameter successfully inferred
println(new CustomisableComparator2(new IdParser)((r1: IdParser#Result, r2: IdParser#Result) => r1 == r2).compare("a", "b"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...