导入所需的外部隐式或合并隐式以获得一个共同的导入
Importing required external implicits or merging implicits to get one common import
我正在创建一个库来使用 Scala 处理固定长度。
为了对 strings
进行编码和解码,我使用基于类型 class 的系统。我已经提供了自己的 Read[A]
和 Write[A]
来处理此操作。
我的 Write
类型 class 在后台使用 Cats
中的 Show
。它有效,但它需要用户显式导入 cats' 隐式,例如:
import com.github.atais.util.Read._
import cats.implicits._
import com.github.atais.util.Write._
示例可以在 Github 项目中看到:
https://github.com/atais/Fixed-Length/blob/702d7d242e5b1f6e1c6b581ad7356f36ca6ed8d9/src/test/scala/com/github/atais/fixedlength/simple/CodecTest.scala
有绕行吗?我想隐藏 cats
导入或(如果可能)将所有三个合并到一个隐式对象中。
cats
将类型类实例存储在特殊特征中,您可以扩展这些特征以将对象本身变成提供者。然而,实例按类型分组,因此您可以获取 Int
、AnyVal
或 List
的所有实例,但不能获取 "anything with Show
".
例如,您可以扩展 AnyValInstances
,因此这将编译(在工作表中)
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
但是有一个警告。由于 Show[Int]
不明确,从 cats
导入实例将导致编译错误:
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))
}
}
以上代码的可运行版本可用here
我正在创建一个库来使用 Scala 处理固定长度。
为了对 strings
进行编码和解码,我使用基于类型 class 的系统。我已经提供了自己的 Read[A]
和 Write[A]
来处理此操作。
我的 Write
类型 class 在后台使用 Cats
中的 Show
。它有效,但它需要用户显式导入 cats' 隐式,例如:
import com.github.atais.util.Read._
import cats.implicits._
import com.github.atais.util.Write._
示例可以在 Github 项目中看到:
https://github.com/atais/Fixed-Length/blob/702d7d242e5b1f6e1c6b581ad7356f36ca6ed8d9/src/test/scala/com/github/atais/fixedlength/simple/CodecTest.scala
有绕行吗?我想隐藏 cats
导入或(如果可能)将所有三个合并到一个隐式对象中。
cats
将类型类实例存储在特殊特征中,您可以扩展这些特征以将对象本身变成提供者。然而,实例按类型分组,因此您可以获取 Int
、AnyVal
或 List
的所有实例,但不能获取 "anything with Show
".
例如,您可以扩展 AnyValInstances
,因此这将编译(在工作表中)
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
但是有一个警告。由于 Show[Int]
不明确,从 cats
导入实例将导致编译错误:
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))
}
}
以上代码的可运行版本可用here