Scalaライブラリのソースを見ると、 shapeless、私はしばしばLowPriorityImplicits
という形質を見つける。Scala型レベルプログラミングで使用される `LowPriorityImplicits`パターンを説明してください。
このパターンを説明していただけますか?どのような問題が解決され、どのようにパターンがそれを解決しますか?
Scalaライブラリのソースを見ると、 shapeless、私はしばしばLowPriorityImplicits
という形質を見つける。Scala型レベルプログラミングで使用される `LowPriorityImplicits`パターンを説明してください。
このパターンを説明していただけますか?どのような問題が解決され、どのようにパターンがそれを解決しますか?
このパターンを使用すると、コンパイラによるあいまい性関連のエラーを回避し、それらの優先順位を付ける方法を提供する、インプリシットの階層を持つことができます。例として次の点を考慮してください
trait MyTypeclass[T] { def foo: String }
object MyTypeclass {
implicit def anyCanBeMyTC[T]: MyTypeclass[T] = new MyTypeclass[T] {
val foo = "any"
}
implicit def specialForString[T](implicit ev: T <:< String): MyTypeclass[T] = new MyTypeclass[T] {
val foo = "string"
}
}
println(implicitly[MyTypeclass[Int]].foo) // Prints "any"
println(implicitly[MyTypeclass[Boolean]].foo) // Prints "any"
println(implicitly[MyTypeclass[String]].foo) // Compilation error
あなたが最後の行に入るエラーがある:
<console>:25: error: ambiguous implicit values:
both method anyCanBeMyTC in object MyTypeclass of type [T]=> MyTypeclass[T]
and method specialForString in object MyTypeclass of type [T](implicit ev: <: <[T,String])MyTypeclass[T]
match expected type MyTypeclass[String]
println(implicitly[MyTypeclass[String]].foo)
暗黙的な解決には曖昧さがありますので、これはコンパイルされません。この場合、暗黙の証拠を使用してimplicit def specialForString: MyTypeclass[String] = ...
と定義し、あいまい性がない場合には、あいまいさを引き起こすために、String
ケースを定義している点で少し擬似です。
trait MyTypeclass[T] { def foo: String }
trait LowPriorityInstances {
implicit def anyCanBeMyTC[T]: MyTypeclass[T] = new MyTypeclass[T] {
val foo = "any"
}
}
object MyTypeclass extends LowPriorityInstances {
implicit def specialForString[T](implicit ev: T <:< String): MyTypeclass[T] = new MyTypeclass[T] {
val foo = "string"
}
}
println(implicitly[MyTypeclass[Int]].foo) // Prints "any"
println(implicitly[MyTypeclass[Boolean]].foo) // Prints "any"
println(implicitly[MyTypeclass[String]].foo) // Prints "string"
をまた、このことは注目に値する。しかし、暗黙のインスタンスを定義し、次のようにあなたはそれを書くことができますし、それが正常に動作している優先度の低いパターンを使用しているときに、他の暗黙のパラメータに依存する必要がある場合がありますパターンは2つのレイヤーに限定されませんが、特質の階層を作成し、より具体的なものからより一般的なものへの継承ツリーへの暗黙の定義を持つことができます。