2011-05-07 77 views
1

的斯卡拉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")) 

它产生如预期的那样,虚假。不幸的是,它从这里下坡。为了允许发烧友对比,我定义:

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")) 
     ^

哦,我期望的在CustomisableComparator中键入变量P将被绑定到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。任何人都可以解释这里发生了什么?

回答

4

你只是要求太多的类型推断。你似乎认为它会为你回溯,事实并非如此。如果您对供应类型

无论你的例子编译:

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")) 
+0

感谢您的解决方案。我仍然困惑于为什么当使用默认和显式参数时“required”类型不同。第一个“必需”表明编译器能够正确推断函数的类型。在第二种情况下,它突然失去了这种能力。 我对于推理者应该能做什么的期望是通过对Haskell的短暂暴露而设定的。它似乎始终能够至少尽可能地推断出,并且通常更多。在这种情况下,推论对我来说显得很明显,所以我希望scalac也能找出答案。 – 2011-05-08 09:14:56