我在以下方面遇到问题:
sealed trait Expression[T] {
def doSomething: Either[String, T]
}
case class Literal(s: String) extends Expression[String] {
def soSomething = Right(s)
}
object Expression{
implicit def encoder[T: Encoder]: Encoder[Expression[T]]
implicit def decoder[T: Decoder]: Decoder[Expression[T]]
}
我看到了几个错误:could not find lazy implicit value of type io.circe.generic.extras.decoding.ConfiguredDecoder[Expression[T]]
not enough arguments for method deriveDecoder: (implicit decode: shapeless.Lazy[ConfiguredDecoder[Expression[T]]])
显然,我遗漏了一个隐含的例子,但我不能从我遵循的Circe例子中看到我遗漏了什么。
有没有人能帮我或指给我一个更好的方法?
干杯
特里
编辑
下面提供的解决方案效果很好,但我正在扩展ADT以涵盖更多情况-我无法编译以下内容:
case class Equals[F[_] <: Expression[_], T](left: F[T], right: F[T]) extends Expression[Boolean]{
def doIt: Either[String, Boolean] = ???
}
object Equals {
implicit def encoder[F[_] <: Expression[_], T](implicit FT: encoder[F[T]]): Encoder[Equals[F, T]] = deriveEncoder
}
我怀疑我没有选择表达式[_]的隐式编码器。我曾尝试将其导入到equals对象中,但没有帮助。任何进一步的建议都将有所帮助,包括如何调试这些问题的建议。
1条答案
按热度按时间pgx2nnw81#
言外之意
意味着为了生成编解码器,Circe必须知道
Expression[T]
对于任意T
具有什么表示(然后为了生成Expression[T]
的编解码器,Circe可以使用针对儿童的编解码器,针对T
的编解码器,等等)。那么代表应该是什么呢?(为简单起见,我写的是
Generic
,而不是LabelledGeneric
)。Expression[String]
具有子级Literal
,因此但例如
Expression[Int]
没有孩子你只知道
所以尝试无条件的暗示(如果你需要的话,也可以尝试存在的暗示)
然后
另请参阅
How to use circe with generic case class that extends a sealed trait
https://github.com/circe/circe/issues/1353
我注意到,在安装了
auto
的semiauto
编解码器的情况下,Expression[T]
的解析度稍好一些。所以我在looked和reify
中介绍了如何手动解析和定义这些编解码器。因此,我们现在不使用auto
方法,而是使用semiauto
方法,并在一个地方显式地重用一些auto
功能。但是,即使使用
auto
,implicitly[Decoder[Expression[Boolean]]]
和implicitly[Encoder[Expression[Boolean]]]
仍然不能编译。恐怕我们已经到了Scala2类型系统(和无形状2)的极限了。Expression[Boolean]
的表示可能是什么?应该是
(Equals[F, _] forSome {type F[_]}) :: Literal2[Boolean] :+: CNil
吗?或
Equals[λ[T => Expression[_]], _] :: Literal2[Boolean] :+: CNil
又名
Equals[({type λ[_] = Expression[_]})#λ, _] :: Literal2[Boolean] :+: CNil
?在Scala 3中,
(Literal, Literal1, Literal2[Boolean], Equals[[_] =>> Expression[?], Any])
又名
Literal *: Literal1 *: Literal2[Boolean] *: Equals[[_] =>> Expression[?], Any] *: EmptyTuple
https://scastie.scala-lang.org/DmytroMitin/jrkBc5lkS1KDQO2U6uMt3Q/1
事实上,这很有趣。如果我们至少有一个通用案例类(
Literal2[T]
),那么原始代码就会编译(可能我从auto
偷来的手动编解码器在某些情况下是不正确的,而且Circe并不完全依赖于无形状的表示)。https://scastie.scala-lang.org/DmytroMitin/m7QZp29yQ3CLeQjOnm3Avw
如果我们删除泛型Case类,代码将无法编译
https://scastie.scala-lang.org/DmytroMitin/m7QZp29yQ3CLeQjOnm3Avw/2
(出于以下目的,让我们将此代码称为(*)。)
我暂时删除了除一个宏之外的所有宏,打开
-Ymacro-debug-lite
后,-Xlog-implicits
将生成macro expansion has failed: Sealed trait Expression[T] has no case class subtypes
,因此显然这是一个Circe错误实际上,
Sealed trait Expression[T] has no case class subtypes
来自无形状原因都是一样的
Shapless认为
Expression[T]
的表示为Literal2[T] :+: CNil
(不包括Literal
和Equals
),如果没有Literal2
,则表示为空。实际上,Shapless没有将
Literal
和Equals
包含在Expression[T]
的表示中,这并不是很好。尽管上面的代码(*)可以编译,但它在运行时失败(抛出异常MatchError
或生成Left
)https://scastie.scala-lang.org/DmytroMitin/m7QZp29yQ3CLeQjOnm3Avw/4
解决方法是手动定义
Expression[T]
的编解码器https://scastie.scala-lang.org/DmytroMitin/m7QZp29yQ3CLeQjOnm3Avw/8
我了解如何修复运行时失败的问题(抛出
MatchError
或生成Left
)。我们应该更换使用
我刚刚将
semiauto.deriveDecoder
/deriveEncoder
的隐式参数DerivedDecoder[Expression[T]]
/DerivedAsObjectEncoder[Expression[T]]
添加到def decoder[T]
/def encoder[T]
。以前这些隐式参数在这里被解析,在def decoder[T]
、def encoder[T]
的定义位置,即对于一般的T
,Expression[T]
的表示是Literal2[T] :+: CNil
,这对于Literal
是失败的。现在,这些隐式参数将在def decoder[T]
、def encoder[T]
的调用点解析,即对于T=String
,Expression[String]
的表示将是Literal :+: Literal2[String] :+: CNil
。(这类似于implicitly[X]
与(implicit x: X)
之间的差异。)(我想,如果在Circe
semiauto.deriveDecoder
/deriveEncoder
中是宏,让用户在必要时向方法添加隐式参数,那会更好。)问题仍然是with
type F has 1 type parameter, but type F has 1
,即Boolean
外壳。https://scastie.scala-lang.org/DmytroMitin/m7QZp29yQ3CLeQjOnm3Avw/11
我怀疑Shapless错误地计算
Expression[Boolean]
的Generic
,因此在表示Equals[_[_] <: Expression[_], _] :+: Literal2[Boolean] :+: CNil
和Generic
的示例中存在无效的Equals[_[_] <: Expression[_], _]
但即使我们修复
Generic
,例如,它将生成Equals2 :+: Literal2[Boolean] :+: CNil
我们将如何为存在的
Equals2
定义Encoder
/Decoder
的示例?