Scala GADT Fantom类型解释器错误:找到任何必需的
我有一个相当平凡的代数Scala GADT Fantom类型解释器错误:找到任何必需的,scala,Scala,我有一个相当平凡的代数 sealed abstract class Kvp[A] case class KvpString(key: String) extends Kvp[String] case class KvpInt(key: String) extends Kvp[Int] case class KvpBool(key: String) extends Kvp[Boolean] case class KvpPair[A,B](p1: Kvp[A], p2: Kvp[B]) extend
sealed abstract class Kvp[A]
case class KvpString(key: String) extends Kvp[String]
case class KvpInt(key: String) extends Kvp[Int]
case class KvpBool(key: String) extends Kvp[Boolean]
case class KvpPair[A,B](p1: Kvp[A], p2: Kvp[B]) extends Kvp[(A,B)]
我试图创建一个解释器,它从Json=>a返回一个函数。但是,我必须键入cast back to a,以便编译代码
import argonaut._, Argonaut._
def eval[A](kvp: Kvp[A]) : Json => A = {
val result = kvp match {
case KvpString(key) =>
(json: Json) =>
json.field(key).flatMap(_.string).get
case KvpInt(key) =>
(json: Json) =>
json.field(key).flatMap(_.number).flatMap(_.toInt).get
case KvpBool(key) =>
(json: Json) =>
json.field(key).flatMap(_.bool).get
case KvpPair(p1, p2) =>
(json: Json) =>
(eval(p1).apply(json), eval(p2).apply(json))
}
result // <-- this would result in the error
result.asInstanceOf[Json => A] // so I have to do this
}
在Cats示例中,这种语法代码样式似乎非常标准,因此,我不确定我在这里做错了什么。问题似乎是Scala编译器不够聪明,无法从
匹配的代码中自动推断出类型Json=>A
:不同分支中的所有返回类型都不同,因此可以推断出类型Json=>Any
。但是,如果有必要的话,对这样一种类型进行打字检查已经足够聪明了。因此,尝试在结果的声明中显式指定类型,如下所示:
val result: (Json => A) = kvp match {
或者删除result
变量,只返回整个kvp match
语句,然后编译器将尝试根据方法的预期返回类型进行类型检查,它也应该可以工作。您是否忘记将KvpPair
的类型参数限制为仅Kvp
s?这样,最后的转换是非常不安全的。@GáborBakos这两个参数是(p1:Kvp[A],p2:Kvp[B]),因此它们必须是Kvp。然而,我认为这可能是一种更合适的编码方式:案例类KvpPair[A1,K1注意,这确实适用于scala编译器,但是Intellij(版本2018.1)将为每个Lamda实体显示一个错误,例如“Int不符合类型a”
val result: (Json => A) = kvp match {