我想用隐式格式化程序定义一个类型安全相等匹配器:
trait Formatter[T] {
def format(t : T) : String
}
implicit val StringFormatter : Formatter[String] = new Formatter[String] { def format(s: String) = s"'$s'" }
implicit def AnyFormatter[T] : Formatter[T] = new Formatter[T] { def format(t : T) = t.toString }
class MatcherOps[T : Formatter]( t : T) {
def must_==(other : T) {
if( t != other ) println( implicitly[Formatter[T]].format(other) ) else println("OK")
}
}
implicit def ToMatcherOps[T : Formatter](t : T) = new MatcherOps[T](t)预期的工作如下:
"ha" must_== "ho"它被编译成(scalac -Xprint:typer)
$anon.this.ToMatcherOps[String]("ha")($anon.this.StringFormatter).must_==("ho");但是,我希望这样做不会编译:
List(1,2) must_== Set(1,2)相反,它将(scalac -Xprint:typer)编译为
$anon.this.ToMatcherOps[Object]($anon.this.ToMatcherOps[List[Int]](immutable.this.List.apply[Int](1, 2))($anon.this.AnyFormatter[List[Int]]))($anon.this.AnyFormatter[Object]).must_==(scala.this.Predef.Set.apply[Int](1, 2))如您所见,ToMatcherOps被调用了两次!
如果我将隐式格式化程序排除在外:
implicit def ToMatcherOps[T](t : T) = new MatcherOps[T](t)那么编译就会像预期的那样失败:
error: type mismatch;
found : scala.collection.immutable.Set[Int]
required: List[Int]
List(1,2) must_== Set(1,2)
^当然,ToMatcherOps无法提供一个合理的Formatter (scalac -Xprint:typer):
implicit private def ToMatcherOps[T >: Nothing <: Any](t: T): this.MatcherOps[T] = new this.MatcherOps[T](t)($anon.this.AnyFormatter[T]);知道怎么解决这个问题吗?谢谢
发布于 2013-10-09 14:33:20
这就是我想出来的。将隐式格式化参数从MatherOps类移到它的方法。
package testpkg
trait Formatter[T] {
def format(x: T): String
}
class MatcherOps[T](x : T) {
def must_==(y: T)(implicit z: Formatter[T]) {
if(x != y)
println(z.format(y))
else
println("OK")
}
}
object Test {
implicit def ToMatcherOps[T](x: T) = new MatcherOps[T](x)
implicit val StringFormatter = new Formatter[String] {
def format(x: String) = "StringFormatter"
}
implicit val ListOfIntFormatter = new Formatter[List[Int]] {
def format(x: List[Int]) = "ListOfIntFormatter"
}
implicit def AnyFormatter[T] = new Formatter[T] {
def format(x: T) = "AnyFormatter"
}
def main(args: Array[String]): Unit = {
List(1,2) must_== List(1,2,3) // ListOfIntFormatter
"string" must_== "another string" // StringFormatter
1 must_== 2 // AnyFormatter
1 must_== false // type mismatch
}
}https://stackoverflow.com/questions/19269537
复制相似问题