cats
は、オブジェクトをプロバイダ自身に変換するために拡張できる特別な特性の中にある型クラスインスタンスを格納します。インスタンスはタイプ別にグループ化されていますので、Int
,AnyVal
またはList
のすべてのインスタンスを取得できますが、「Show
を持つもの」は使用できません。
ただし、注意点があります
import cats.Show
import cats.instances.AnyValInstances
trait Write[A]
object Write extends AnyValInstances {
implicit def writeForCatsShow[A](implicit s: Show[A]): Write[A] = new Write[A] { }
}
import Write._
implicitly[Write[Int]] // Show[Int] is in scope
たとえば、あなたはAnyValInstances
を拡張することができますので、これは(ワークシートで)コンパイルします。 cats
からインスタンスをインポートすると、曖昧であることに起因Show[Int]
にコンパイルエラーが発生します。
import Write._
import cats.implicits._
// implicitly[Write[Int]] // this will fail to compile b/c we have Show[Int] twice
私の好みは、すべての輸入品をユーザーに負担をかけないようするために、いくつかの定型的なコードを書くことになります。
object file1 {
// pretend it's a different file
import cats.Show
import cats.implicits._
trait Write[A]
object Write {
// implement generic Show <-> Write here
private def fromShow[A](implicit s: Show[A]): Write[A] = new Write[A] { }
// manually create instances for types you need
implicit val intWrite = fromShow[Int]
implicit val longWrite = fromShow[Long]
implicit val doubleWrite = fromShow[Double]
implicit val stringWrite = fromShow[String]
// BONUS: define instances for other types that have Show
// without causing any ambiguities
implicit def listWrite[A](implicit wa: Write[A]): Write[List[A]] = ???
}
}
object file2 {
import file1.Write
object Methods {
def testWrite[A](a: A)(implicit write: Write[A]) = 42
}
}
object file3 {
import file2.Methods
// We don't need to import cats.Show OR Write at all
// because Show instances are resolved in object Write code
// and Scala automatically looks up Write[A] instances in
// companion object, so Write[Double] will be picked
def main(args: Array[String]) = {
println(Methods.testWrite(2.11))
}
}
上記コードのRunnableをバージョンはhere
利用可能です