gpt4 book ai didi

scala - Typeclass 的模棱两可的隐含值

转载 作者:行者123 更新时间:2023-12-01 11:15:55 26 4
gpt4 key购买 nike

我正在尝试抽象出针对特定类型触发的 json 解析逻辑。

我开始创建 Parser 特征,如下所示:

trait Parser {
def parse[T](payload : String) : Try[T]
}

我有一个名为 JsonParser 的特性的实现,它是:
class JsonParser extends Parser {

override def parse[T](payload: String): Try[T] = parseInternal(payload)

private def parseInternal[T:JsonParserLike](payload:String):Try[T] = {
implicitly[JsonParserLike[T]].parse(payload)
}
}

JsonParserLike 定义如下:
trait JsonParserLike[T] {
def parse(payload: String): Try[T]
}

object JsonParserLike {
implicit val type1Parser:JsonParserLike[Type1] = new JsonParserLike[Type1]
{
//json parsing logic for Type1
}

implicit val type2Parser:JsonParserLike[Type2] = new JsonParserLike[Type2]
{
//json parsing logic for Type2
}
}

当我尝试编译上述内容时,编译失败并显示:
ambiguous implicit values:
[error] both value type1Parse in object JsonParserLike of type => parser.jsonutil.JsonParserLike[parser.models.Type1]
[error] and value type2Parser in object JsonParserLike of type => parser.jsonutil.JsonParserLike[parser.models.Type2]
[error] match expected type parser.jsonutil.JsonParserLike[T]
[error] override def parse[T](payload: String): Try[T] = parseInternal(payload)

不知道为什么隐式解析在这里失败。是因为 parse Parser 中的方法trait 没有类型参数 T 的参数?

我尝试了另一种方法如下:
trait Parser {
def parse[T](payload : String) : Try[T]
}

class JsonParser extends Parser {

override def parse[T](payload: String): Try[T] = {
import workflow.parser.JsonParserLike._
parseInternal[T](payload)
}

private def parseInternal[U](payload:String)(implicit c:JsonParserLike[U]):Try[U] = {
c.parse(payload)
}
}

以上给了我以下错误:
could not find implicit value for parameter c: parser.JsonParserLike[T]
[error] parseInternal[T](payload)
[error]

^

编辑:从 REPL 添加 session
scala> case class Type1(name: String)
defined class Type1

scala> case class Type2(name:String)
defined class Type2

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.util.{Failure, Success, Try}

trait JsonParserLike[+T] {
def parse(payload: String): Try[T]
}

object JsonParserLike {

implicit val type1Parser:JsonParserLike[Type1] = new JsonParserLike[Type1] {

override def parse(payload: String): Try[Type1] = Success(Type1("type1"))
}

implicit val type2Parser:JsonParserLike[Type2] = new JsonParserLike[Type2] {

override def parse(payload: String): Try[Type2] = Success(Type2("type2"))
}
}

// Exiting paste mode, now interpreting.

import scala.util.{Failure, Success, Try}
defined trait JsonParserLike
defined object JsonParserLike

scala> :paste
// Entering paste mode (ctrl-D to finish)

trait Parser {
def parse[T](payload : String) : Try[T]
}

class JsonParser extends Parser {

override def parse[T](payload: String): Try[T] = parseInternal(payload)

private def parseInternal[T:JsonParserLike](payload:String):Try[T] = {
implicitly[JsonParserLike[T]].parse(payload)
}
}

// Exiting paste mode, now interpreting.

<pastie>:24: error: ambiguous implicit values:
both value type1Parser in object JsonParserLike of type => JsonParserLike[Type1]
and value type2Parser in object JsonParserLike of type => JsonParserLike[Type2]
match expected type JsonParserLike[T]
override def parse[T](payload: String): Try[T] = parseInternal(payload)

最佳答案

正如我已经尝试在评论中解释的那样,问题在于方法

override def parse[T](payload: String): Try[T] = parseInternal(payload)

不接受任何 JsonParserLike[T]实例。因此,编译器无法插入 JsonParserLike[T] 的正确实例。在调用站点(类型 T 是已知的)。

要使其工作,必须添加某种唯一标识类型 T 的 token 。到 parse 的参数列表.一种粗略的方法是添加 JsonParserLike[T]本身:
import util.Try

trait Parser {
def parse[T: JsonParserLike](payload : String) : Try[T]
}

class JsonParser extends Parser {

override def parse[T: JsonParserLike](payload: String): Try[T] =
parseInternal(payload)

private def parseInternal[T:JsonParserLike](payload:String):Try[T] = {
implicitly[JsonParserLike[T]].parse(payload)
}
}

trait JsonParserLike[T] {
def parse(payload: String): Try[T]
}

object JsonParserLike {
implicit val type1Parser: JsonParserLike[String] = ???
implicit val type2Parser: JsonParserLike[Int] = ???
}

现在它可以编译了,因为 JsonParserLike[T] parseInternal 要求作为隐式参数自动插入到 parse .

这可能不是您想要的,因为它在 Parser 之间创建了硬依赖关系。接口(interface)和 JsonParserLike类型类。您可能想从 shapeless.Typeable 之类的东西中获得一些灵感。摆脱 JsonParserLikeParser接口(interface),或者只依赖 circe马上。

关于scala - Typeclass 的模棱两可的隐含值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51352288/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com