使用默认值Scala多个隐式参数会导致值不明确

irr*_*lar 3 scala implicit

我一直在讨论从3种方法中重构公共代码的问题,makeRequest()但是我从编译器得到了模糊的隐式匹配.我不确定这是否来自隐式方法或其他问题的默认值,但我的目标是getRequest/deleteRequest/postRequest可以简单地调用makeRequest("GET")/ makeRequest("DELETE")/ makeRequest("POST") ).以前没有任何参数是隐含的,我只是试图通过使用implicits来达到目标

def makeRequest(method: String)(implicit path: String, base: String, params: Seq[(String, String)], body: Option[String], retriesLeft: Int): Future[WSResponse] = ???

def getRequest()(implicit path: String, base: String = baseUrl, params: Seq[(String, String)] = Seq(), body: Option[String] = None, retriesLeft: Int = retries): Future[WSResponse] = makeRequest("GET")

def deleteRequest()(implicit path: String, base: String = baseUrl, params: Seq[(String, String)] = Seq(), body: Option[String] = None, retriesLeft: Int = retries): Future[WSResponse] = makeRequest("GET")

def postRequest[T]()(path: String, body: T, base: String = baseUrl, params: Seq[(String, String)] = Seq(), retriesLeft: Int = retries)
  (implicit wrt: play.api.http.Writeable[T], ct : play.api.http.ContentTypeOf[T]): Future[WSResponse] = makeRequest("POST")
Run Code Online (Sandbox Code Playgroud)

我得到这个和deleteRequest相同

ambiguous implicit values:
[error]  both value base of type String
[error]  and value path of type String
[error]  match expected type String
[error]     def getRequest()(implicit path: String, base: String = baseUrl, params: Seq[(String, String)] = Seq(), body: Option[String] = None, retriesLeft: Int = retries): Future[WSResponse] = makeRequest("GET")
Run Code Online (Sandbox Code Playgroud)

mar*_*ios 9

我认为除非你正在做一些非常时髦的DSL,否则你应该重新使用所有这些隐含的东西.

这是解决您遇到的问题的一种方法.正如您可能已经猜到的那样,对Type的隐式工作而不是名称,因此具有两个隐式具有相同类型的是No-No.

从Scala 2.10开始,Scala允许您使用AnyVal(SIP-15)"内联"类.以下是所谓的值类的示例:

case class Path(p: String) extends AnyVal
Run Code Online (Sandbox Code Playgroud)

现在,不是使用字符串来表示您的实体,而是将它们包含在这个漂亮的"包装器"类中.关于这一点很酷的是编译器将在编译期间用String替换代码中的所有Path对象.因此,就编译代码而言,您将获得与使用String时相同的性能.您可以获得很多类型安全性而无需支付运行时间罚款.

现在回到你的案例,这里是如何解决你的问题:

case class Path(s: String) extends AnyVal
case class BaseUrl(s: String) extends AnyVal

def foo(implicit a: Path, b: BaseUrl) = a.s ++ b.s

implicit val a: Path = Path("a")
implicit val b: BaseUrl = BaseUrl("b")
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它:

scala> foo
res0: String = ab
Run Code Online (Sandbox Code Playgroud)