如何用scala中的编码器类型类处理Option



我有一个经典的Encoder类型类。

trait Encoder[A] {
def encode(a: A): String
}

我有两个问题

问题1:分歧来自哪里:

[error] … diverging implicit expansion for type sbopt.Test.Encoder[None.type]
[error] starting with value stringEncoder in object Test
[error]   show(None)
implicit val stringEncoder = new Encoder[String] {
override def encode(a: String): String = a
}
implicit def optionEncoder[A: Encoder]: Encoder[Option[A]] =
(a: Option[A]) => {
val encoderA = implicitly[Encoder[A]]
a.fold("")(encoderA.encode)
}
implicit def someEncoder[A: Encoder]: Encoder[Some[A]] =
(a: Some[A]) => {
val encoderA = implicitly[Encoder[A]]
encoderA.encode(a.get)
}
implicit def noneEncoder[A: Encoder]: Encoder[None.type] =
(_: None.type) => ""
def show[A: Encoder](a: A) = println(implicitly[Encoder[A]].encode(a))
show(None)

问题2:我在电路中看到编码器不是逆变的。利弊是什么?

trait Encoder[-A] {
def encode(a: A): String
}
implicit val stringEncoder: Encoder[String] = (a: String) => a
implicit def optionEncoder[A: Encoder]: Encoder[Option[A]] =
(a: Option[A]) => {
val encoderA = implicitly[Encoder[A]]
a.fold("")(encoderA.encode)
}
def show[A: Encoder](a: A) = println(implicitly[Encoder[A]].encode(a))
show(Option("value"))
show(Some("value"))
show(None)

关于1.

你对noneEncoder的定义不好。您有一个额外的上下文绑定(甚至还有额外的类型参数(。

implicit def noneEncoder/*[A: Encoder]*/: Encoder[None.type] =
(_: None.type) => ""

它编译:

show[Option[String]](None)
show[None.type](None)
show(None)

您对noneEncoder的原始定义意味着,如果您有某个A的实例(不受约束,即推断(,则您有None.typeEncoder实例。通常情况下,如果您有唯一的隐式(或至少是唯一的更高优先级隐式(,这会起作用。例如,如果只有stringEncoder和原始noneEncoder,则show[None.type](None)show(None)将编译。

关于2.

PROS带有反变体Encoder

trait Encoder[-A] {
def encode(a: A): String
}

你可以去掉someEncodernoneEncoderoptionEncoder就足够了

show(Some("a"))
show[Option[String]](Some("a"))
show[Option[String]](None)
show[None.type](None)
show(None)

CONS有些人认为反变类型类的行为违反直觉:

https://github.com/scala/bug/issues/2509

https://groups.google.com/g/scala-language/c/ZE83TvSWpT4/m/YiwJJLZRmlcJ

也许也有关系:在scala 2.13中,如何隐式使用[value singleton type]?

相关内容

  • 没有找到相关文章

最新更新