在这种情况下,scala的类型检查如何工作? [英] how does scala's type check work in this case?

查看:58
本文介绍了在这种情况下,scala的类型检查如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

// Start writing your ScalaFiddle code here
sealed trait DSL[A]{
  // def run(): A ={
  //   this match {
  //     case GetLength(something) =>
  //       something.length
  //     case ShowResult(number) =>
  //       s"the length is $number"
  //   }
  // }
}

case class GetLength(something: String) extends DSL[Int]
case class ShowResult(number: Int) extends DSL[String]

def run[A](fa:DSL[A]): A ={
  fa match {
    case GetLength(something) =>
      something.length
    case ShowResult(number) =>
      s"the length is $number"
  }
}

val dslGetLength = GetLength("123456789")
val length = run(dslGetLength)
val dslShowResult = ShowResult(length)
println(run(dslShowResult))
// print: the length is 9

在此处scalafiddle

  • 为什么 run 函数不能在 DSL [A] 特性中编译,但可以在外部工作?
  • 在这种情况下,类型推断如何工作?
  • why does the run function not compile in the DSL[A] trait, but worked outside?
  • how does type inference work in this case?

推荐答案

这是广义抽象数据类型的情况.

This is a case of generalized abstract data type.

当您有 DSL [A] 且函数返回 A 时,编译器可以证明:

When you have a DSL[A] and function returning A, compiler can prove that:

  • 用于 case GetLength A = Int ,因此您可以在那里返回 Int
  • 用于 case ShowResult A = String ,因此您可以返回 String
  • for case GetLength A=Int so you can return Int there
  • for case ShowResult A=String so you can return String

但是,众所周知,Scala 2没有对GADT的完美支持,因此有时编译器即使可以工作也会失败.我猜有些编译器开发人员可以弄清楚确切的情况,但是有趣的是,它可以解决:

however, Scala 2 is known to not have a perfect support of GADTs, so sometimes compiler fails, even if it should work. I guess some compiler dev could figure out the exact case, but, interestingly, it can be worked around with:

sealed trait DSL[A]{
  def run(): A = DSL.run(this)
}
object DSL {
  def run[A](fa:DSL[A]): A ={
    fa match {
      case GetLength(something) =>
        something.length
      case ShowResult(number) =>
        s"the length is $number"
    }
  }
}

case class GetLength(something: String) extends DSL[Int]
case class ShowResult(number: Int) extends DSL[String]

我的疯狂猜测是,通用方法中的模式匹配在编译器中是一种特殊情况,当 A 固定时不会触发.我认为是这样,因为以下代码也可以工作:

My wild guess would be that pattern matching in a generic method is kind of a special case in a compiler, which is not triggered when A is fixed. I think that, because the following code also works:

sealed trait DSL[A]{
  def run(): A = runMe(this)
  private def runMe[B](dsl: DSL[B]): B = {
    dsl match {
      case GetLength(something) =>
        something.length
      case ShowResult(number) =>
        s"the length is $number"
    }
  }
}

这同样会失败:

sealed trait DSL[A]{
  def run(): A = {
    val fa: DSL[A] = this // make sure error is not related to special treatment of "this", this.type, etc
    fa match {
      case GetLength(something) =>
        something.length
      case ShowResult(number) =>
        s"the length is $number"
    }
  }
}

cmd4.sc:5: constructor cannot be instantiated to expected type;
 found   : ammonite.$sess.cmd4.GetLength
 required: ammonite.$sess.cmd4.DSL[A]
      case GetLength(something) =>
           ^
cmd4.sc:7: constructor cannot be instantiated to expected type;
 found   : ammonite.$sess.cmd4.ShowResult
 required: ammonite.$sess.cmd4.DSL[A]
      case ShowResult(number) =>
           ^
Compilation Failed

换句话说,我怀疑类型参数会改变事物的评估方式:

In other words, I suspect that type parameter change how things are being evaluated:

  • def runMe [B](dsl:DSL [B]):B 具有类型参数,因此 match case 的结果>与 B 进行比较,在每种情况下,可以证明 B 的值是某种特定类型(Int,String)
  • def run:A 中,但是以某种方式阻止了编译器进行这种分析-恕我直言,这是一个bug,但这也许是某些晦涩功能的结果.
  • def runMe[B](dsl: DSL[B]): B has a type parameter, so results of each case inside match are compared against B where for each case value of B can be proven to be some specific type (Int, String)
  • in def run: A however compiler is somehow prevented from making such analysis - IMHO it is a bug, but perhaps it is a result of some obscure feature.

从我看到的相同错误中发现了Dotty,所以它要么是重复的错误,要么是类型级别检查器的限制(毕竟,所有GADT尚未广泛使用din Scala)-我建议将问题报告给Scala/Dotty团队让他们决定是什么.

From what I see the same error occurs in Dotty, so it is either duplicated bug or a limitation of a type-level checker (after all GADT aren't widely use din Scala, yet) - I would suggest reporting issue to Scala/Dotty team and letting them decide what it is.

这篇关于在这种情况下,scala的类型检查如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆