[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[[email protected]@[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[[email protected]@[String,foo.tags.Social]]
[error] implicitly[QueryParamDecoder[String @@ Social]]
[error] ^
मैं instances._
आयात करता हूं; instances
ExternalInstances1
बढ़ाता है, और ExternalInstances1
ExternalInstances0
बढ़ाता है। इस विरासत की वजह से मैं ExternalInstances1
के सदस्यों को अस्पष्टता प्रदान करने के बजाय ExternalInstances0
से अधिक जीतने की उम्मीद करूंगा।प्राथमिकता के बावजूद मुझे "संदिग्ध निहितार्थ" त्रुटि क्यों मिलती है?
यह क्यों हो रहा है, और मैं इसे कैसे ठीक कर सकता हूं? धन्यवाद।
स्रोत http://scastie.org/12233 पर है, नीचे reproduced:
/***
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))
}
}
आप 'implicits' को प्राथमिकता नहीं दे सकते। विरासत के माध्यम से आप केवल प्रारंभिक आदेश को प्रभावित कर सकते हैं। यदि आप 'बाहरीInstances1' से * जीत * के अंतर्निहित चाहते हैं, तो आपको 'बाहरीInstances0' के' implicits 'को ओवरराइड करना चाहिए। –
@ सस्चा कोलबर्ग: हाँ आप कर सकते हैं, और यह एक आम स्केल मुहावरे है। उदाहरण के द्वारा देखें: http://stackoverflow.com/questions/1886953/is-there-a-way-to-control-which-implicit-conversion-will-be-the-default-used –
एचएम, मेरा बुरा, didn यह नहीं पता। खैर, जैसा कि आपके दो निहित रूपांतरणों में थोड़ा अलग हस्ताक्षर हैं, मुझे लगता है कि विरासत से कम प्राथमिकता वाले रूपांतरण के हस्ताक्षर के लिए बेहतर स्कोर हो सकता है और एक अजीब दुर्घटना के कारण वे दोनों एक ही स्कोर के साथ समाप्त हो जाते हैं। लेकिन मैं इसे डीबग करने वाला व्यक्ति नहीं बनना चाहता;) –