Scala GADT Fantom Type解释器错误:找到任何必需的A

时间:2018-12-01 14:05:15

标签: 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]) extends Kvp[(A,B)]

我正在尝试创建一个解释器,该解释器从Json => A返回一个函数。但是,我必须将强制类型转换回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
 }

如果result是最后一条语句,则在编译时会出现此错误。

[error]  found   : argonaut.Json => Any
[error]  required: argonaut.Json => A
[error]     result

在Cats示例中,这种语法代码样式似乎很标准,所以我不确定在这里做错了什么。

1 个答案:

答案 0 :(得分:1)

问题似乎是Scala编译器不够聪明,无法从Json => A / match的代码中自动推断出类型case:所有返回类型都不同分支是不同的,因此推断类型Json => Any。但是,如果必须的话,可以对这种类型进行类型检查非常聪明。因此,尝试在result的声明中明确指定类型,如下所示:

  val result: (Json => A) = kvp match {

或者删除result变量,然后只返回整个kvp match语句,然后编译器将尝试对方法的预期返回类型进行类型检查,并且应该也可以工作。