简体   繁体   English

导入所需的外部隐式或合并隐式以获取一个公共导入

[英]Importing required external implicits or merging implicits to get one common import

I am creating a library to handle fixed-length using Scala. 我正在创建一个使用Scala处理固定长度的库。

For encoding and decoding the strings I use type class based system. 为了对strings进行编码和解码,我使用基于类型类的系统。 I have provided my own Read[A] and Write[A] for handling this actions. 我提供了自己的Read[A]Write[A]来处理此操作。

My Write type class is using Show from Cats under the hood. 我的Write类型课使用引擎盖下的Show from Cats It works, but it requires the user to explicitly import cats' implicits, like: 它可以工作,但是需要用户显式导入cat的隐式内容,例如:

import com.github.atais.util.Read._
import cats.implicits._
import com.github.atais.util.Write._

the example could be seen on the Github project: 该示例可以在Github项目上看到:
https://github.com/atais/Fixed-Length/blob/702d7d242e5b1f6e1c6b581ad7356f36ca6ed8d9/src/test/scala/com/github/atais/fixedlength/simple/CodecTest.scala https://github.com/atais/Fixed-Length/blob/702d7d242e5b1f6e1c6b581ad7356f36ca6ed8d9/src/test/scala/com/github/atais/fixedlength/simple/CodecTest.scala

Is there any walk-around? 有没有四处走走? I would like to hide the cats import or (if possible) merge all three into a single implicit object. 我想隐藏cats导入或(如果可能)将所有三个cats合并为一个隐式对象。

cats stores typeclass instances inside special traits that you can extend to turn your objects into providers themselves. cats将类型类实例存储在特殊特征内,您可以扩展这些特征以将对象本身变成提供程序。 Instances are grouped by type however, so you can take all instances for Int , AnyVal or List , but not "anything with Show ". 实例按类型分组然而,这样你就可以采取所有实例IntAnyValList ,而不是“与任何Show ”。

For example, you can extend AnyValInstances , so this will compile (in a worksheet) 例如,您可以扩展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

There is a caveat, however. 但是,有一个警告。 Importing instances from cats will cause compilation error due to Show[Int] being ambiguous: 由于Show[Int]含糊不清,因此从cats导入实例将导致编译错误:

import Write._
import cats.implicits._

// implicitly[Write[Int]] // this will fail to compile b/c we have Show[Int] twice

My preference would be to write some boilerplate code to avoid burdening users with imports at all. 我更喜欢编写一些样板代码,以免完全使用户负担导入。

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 version of above code is available here 以上代码的可运行版本在此处提供

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM