scala – 尽管优先考虑了implicits,为什么我会收到“含糊不清的
发布时间:2020-12-16 18:49:18 所属栏目:安全 来源:网络整理
导读:[error] test.scala:31: ambiguous implicit values:[error] both method taggedQueryParamDecoder in trait ExternalInstances0 of type [A,T](implicit evidence$2: org.http4s.QueryParamDecoder[A])org.http4s.QueryParamDecoder[scalaz.@@[A,T]][error]
[error] test.scala:31: ambiguous implicit values: [error] both method taggedQueryParamDecoder in trait ExternalInstances0 of type [A,T](implicit evidence$2: org.http4s.QueryParamDecoder[A])org.http4s.QueryParamDecoder[scalaz.@@[A,T]] [error] and method iiQueryParamDecoder in trait ExternalInstances1 of type [B](implicit ii: foo.InvariantInstances[B])org.http4s.QueryParamDecoder[B] [error] match expected type org.http4s.QueryParamDecoder[scalaz.@@[String,foo.tags.Social]] [error] implicitly[QueryParamDecoder[String @@ Social]] [error] ^ 我导入instances._;实例扩展了ExternalInstances1,ExternalInstances1扩展了ExternalInstances0.由于这种继承,我希望ExternalInstances1的成员能够胜过ExternalInstances0,而不是产生歧义. 为什么会发生这种情况,我该如何解决?谢谢. 来源是http://scastie.org/12233,转载如下: /*** scalaVersion := "2.11.7" libraryDependencies += "org.http4s" %% "http4s-core" % "0.10.0" resolvers ++= Seq( "tpolecat" at "http://dl.bintray.com/tpolecat/maven","Scalaz Bintray Repo" at "http://dl.bintray.com/scalaz/releases",Resolver.sonatypeRepo("releases") ) libraryDependencies += "org.tpolecat" %% "doobie-core" % "0.2.2" libraryDependencies += "com.github.alexarchambault" %% "argonaut-shapeless_6.1" % "0.3.1" */ import java.time.LocalDate import argonaut._,Argonaut._ import doobie.imports._ import doobie.util.composite.Composite import tags._ import instances._ import org.http4s._ import scala.reflect.runtime.universe.TypeTag import scalaz._ object Main extends App { implicitly[QueryParamDecoder[String @@ Social]] println("ok") } object tags { trait Social; val Social = Tag.of[Social] } object instances extends ExternalInstances1 { implicit val ssn: InvariantInstances[String @@ Social] = InvariantInstances { (raw: String) ? val digitsOnly = raw.filter(_.isDigit) require(digitsOnly.length == 9) Social(digitsOnly) }(Social.unwrap) } trait ExternalInstances1 extends ExternalInstances0 { implicit def iiCodecJson[B](implicit ii: InvariantInstances[B]): CodecJson[B] = ii.codecJson implicit def iiEncodeJson[B](implicit ii: InvariantInstances[B]): EncodeJson[B] = ii.encodeJson implicit def iiDecodeJson[B](implicit ii: InvariantInstances[B]): DecodeJson[B] = ii.decodeJson implicit def iiMeta[B](implicit ii: InvariantInstances[B]): Meta[B] = ii.meta implicit def iiQueryParamEncoder[B](implicit ii: InvariantInstances[B]): QueryParamEncoder[B] = ii.queryParamEncoder implicit def iiQueryParamDecoder[B](implicit ii: InvariantInstances[B]): QueryParamDecoder[B] = ii.queryParamDecoder } trait ExternalInstances0 { implicit def taggedEncodeJson[A,T](implicit A: EncodeJson[A]): EncodeJson[A @@ T] = A.contramap(Tag.of[T].unwrap) implicit def taggedDecodeJson[A,T](implicit A: DecodeJson[A]): DecodeJson[A @@ T] = A.map(Tag.of[T].apply) implicit def taggedComposite[A: Composite,T]: Composite[A @@ T] = Composite[A].xmap(a => Tag[A,T](a),Tag.unwrap(_)) implicit def taggedQueryParamDecoder[A: QueryParamDecoder,T]: QueryParamDecoder[A @@ T] = QueryParamDecoder.decodeBy(Tag.of[T](_: A)) } trait InvariantInstances[B] { def codecJson: CodecJson[B] def decodeJson: DecodeJson[B] def encodeJson: EncodeJson[B] def meta: Meta[B] def queryParamEncoder: QueryParamEncoder[B] def queryParamDecoder: QueryParamDecoder[B] } object InvariantInstances { def apply[A: EncodeJson: DecodeJson: Meta: QueryParamDecoder: QueryParamEncoder,B: TypeTag](f: A ? B)(g: B ? A) = new InvariantInstances[B] { def codecJson: CodecJson[B] = CodecJson.derived[B](encodeJson,decodeJson) def decodeJson: DecodeJson[B] = implicitly[DecodeJson[A]].map(f) def encodeJson: EncodeJson[B] = implicitly[EncodeJson[A]].contramap(g) def meta: Meta[B] = implicitly[Meta[A]].xmap(f,g) def queryParamDecoder: QueryParamDecoder[B] = CovariantInstances.queryParamDecoder(f) def queryParamEncoder: QueryParamEncoder[B] = ContravariantInstances.queryParamEncoder(g) } } object CovariantInstances { def queryParamDecoder[A,B](f: A ? B)(implicit A: QueryParamDecoder[A],B: reflect.runtime.universe.TypeTag[B]): QueryParamDecoder[B] = new QueryParamDecoder[B] { import scalaz.Validation.FlatMap._ // suppress deprecation warning def decode(value: QueryParameterValue): ValidationNel[ParseFailure,B] = A.decode(value).flatMap( a ? Validation.fromTryCatchNonFatal(f(a)).leftMap(t => ParseFailure(s"Query decoding ${B.tpe.typeSymbol} failed",t.getMessage) ).toValidationNel ) } } object ContravariantInstances { def queryParamEncoder[A,B](g: B ? A)(implicit A: QueryParamEncoder[A]): QueryParamEncoder[B] = new QueryParamEncoder[B] { def encode(value: B): QueryParameterValue = A.encode(g(value)) } } 解决方法
根据Sasha Kolberg的评论和
http://eed3si9n.com/revisiting-implicits-without-import-tax,我想我在ExternalInstances0(1分)中有一个“更具体”的定义,在ExternalInstances1(1分)中有一个“更高优先级”的定义,导致一个平局和歧义.
我的解决方法是在ExternalInstances1(2分?)中添加一个“更具体,更高优先级”的定义来打破平局,即使它是重复的代码,它基本上是样板文件. 我想知道一个更好的解决方案.谢谢! trait ExternalInstances1 extends ExternalInstances0 { implicit def iiCodecJson[B](implicit ii: InvariantInstances[B]): CodecJson[B] = ii.codecJson implicit def iiEncodeJson[B](implicit ii: InvariantInstances[B]): EncodeJson[B] = ii.encodeJson implicit def iiDecodeJson[B](implicit ii: InvariantInstances[B]): DecodeJson[B] = ii.decodeJson implicit def iiMeta[B](implicit ii: InvariantInstances[B]): Meta[B] = ii.meta implicit def iiQueryParamEncoder[B](implicit ii: InvariantInstances[B]): QueryParamEncoder[B] = ii.queryParamEncoder implicit def iiQueryParamDecoder[B](implicit ii: InvariantInstances[B]): QueryParamDecoder[B] = ii.queryParamDecoder implicit def iiCodecJsonT[B,T](implicit ii: InvariantInstances[B @@ T]): CodecJson[B @@ T] = ii.codecJson implicit def iiEncodeJsonT[B,T](implicit ii: InvariantInstances[B @@ T]): EncodeJson[B @@ T] = ii.encodeJson implicit def iiDecodeJsonT[B,T](implicit ii: InvariantInstances[B @@ T]): DecodeJson[B @@ T] = ii.decodeJson implicit def iiMetaT[B,T](implicit ii: InvariantInstances[B @@ T]): Meta[B @@ T] = ii.meta implicit def iiQueryParamEncoderT[B,T](implicit ii: InvariantInstances[B @@ T]): QueryParamEncoder[B @@ T] = ii.queryParamEncoder implicit def iiQueryParamDecoderT[B,T](implicit ii: InvariantInstances[B @@ T]): QueryParamDecoder[B @@ T] = ii.queryParamDecoder } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |