В 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
. Кто-нибудь может объяснить, что здесь происходит?