暗黙のフォーマッタを使用して、タイプ セーフな等号マッチャーを定義したいと考えています。
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 が 2 回呼び出されています。
暗黙のフォーマッターを邪魔にならないようにすると:
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]);
これを回避する方法はありますか?ありがとう