【问题标题】:Scala unexpected type inference troubleshootingScala 意外类型推断故障排除
【发布时间】:2014-12-11 23:23:38
【问题描述】:

我一直在为O 输出类型的错误类型推断而苦苦挣扎。为什么 scalac 看到 Int 而不是 (Int,String) ? :

trait Request[I,+O,C[_]]
case class Get[I, O, C[_]](storeName: String, arg: C[I]) extends Request[I,(I,O),C]
object Question {
  val get: Request[Int,(Int,String), List] = Get("play", List(1))
}

[error]  found   : com.viagraphs.idb.Get[Int,Int,List]
[error]  required: com.viagraphs.idb.Request[Int,(Int, String),List]
[error]       val get: Request[Int,(Int,String), List] = Get("play", List(1))

请忽略 W,R,ValidKey 类型的类,我猜它们在这里无关紧要。

完全一样的事情发生在这种情况下:

case class Append[I : W, O : R : ValidKey](storeName: String, arg: List[I]) extends Request[I,(O,I),List]
object Question {
  val get: Request[Int,(Int,String), List] = Get("play", List(1))
}
val append: Request[String,(Int,String), List] = Append("play", List("foo"))

[error]  found   : com.viagraphs.idb.Append[String,String]
[error]  required: com.viagraphs.idb.Request[String,(Int, String),List]
[error]       val append: Request[String,(Int,String), List] = Append("play", List("foo"))

我尝试使用 -Ytyper-debug 来处理这个问题,但它确实是硬核的东西,我不了解它的机制。

更新:我使用 Ordering 类型类复制了它,知道不满足什么隐式解析规则吗?

  trait Req[I,O]
  case class Insert[I : Ordering, O : Ordering](arg: I) extends Req[I,O]
  def execute[I,O](req: Req[I,O]): O = null.asInstanceOf[O]

  def main() = {
    val result: Int = execute(Insert("test"))  
  }

error: type mismatch;
 found   : String
 required: Int
    val result: Int = execute(Insert("test"))  

【问题讨论】:

  • 第一个例子编译
  • 这可能是一个错误,它使用与我在 SBT 项目中使用的相同 scala 版本在 REPL 中编译,但它无法编译..

标签: scala type-inference scalac


【解决方案1】:

好的,我试着整理一个简单的例子,它在我的机器上编译得很好,在 scala 2.11.4 上使用 sbt 0.13.7

package example

object Main extends App {
  trait Request[I,+O,C[_]]

  trait W[A]
  trait R[A]
  trait ValidKey[A]

  implicit val wString = new W[String]{}
  implicit val rInt = new R[Int]{}
  implicit val validKeyInt = new ValidKey[Int]{}

  case class Append[I: W, O: R : ValidKey](storeName: String, arg: List[I]) extends Request[I,(O,I),List]
  val append: Request[String,(Int,String), List] = Append("play", List("foo"))

}

我错过了什么吗?

【讨论】:

  • 哇,那一定是那些类型类引起的,因为我也可以编译它。我想这是推断这些类型时 TC 隐含证据解析的问题。很可能是 uPickle Reader/Writer 类型类导致它:-/
  • 其实原来的原因是这样的:github.com/lihaoyi/upickle/issues/52
  • 我更新了问题,这似乎是类型推断结合类型类的普遍问题。我只是不知道是什么问题
【解决方案2】:

试着改成这样:

Get[Int, String, List]("play", List(1))

我能够在 Intellij 中重现您的问题,尽管它有不同的类型推断问题,但这似乎使错误消失了。

【讨论】:

  • 嗯,这不是类型推断,这是经典的类型声明......我希望用户/调用者能够避免它,以便可以推断类型,但它显然不起作用.如果您执行类似 result.flatMap { value: Infered[Types] => 之类的操作,则更明显
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-15
  • 2010-11-30
相关资源
最近更新 更多