Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 2.11.8类型标记并非总是由编译器正确生成_Scala - Fatal编程技术网

Scala 2.11.8类型标记并非总是由编译器正确生成

Scala 2.11.8类型标记并非总是由编译器正确生成,scala,Scala,有人能向我解释一下(或重定向到参考资料)为什么在这种特殊情况下,类型标记没有“正确”生成: class A(s: Seq[_]*) def toto[T: TypeTag](p: Seq[T]): Seq[T] = { println(typeTag[T].tpe) p } val data = Seq( ("a", "a") ) val x = data.map(_._1) new A( toto(x), toto(data.map(_._2)), toto[Strin

有人能向我解释一下(或重定向到参考资料)为什么在这种特殊情况下,类型标记没有“正确”生成:

class A(s: Seq[_]*)

def toto[T: TypeTag](p: Seq[T]): Seq[T] = {
  println(typeTag[T].tpe)
  p
}

val data = Seq( ("a", "a") )
val x = data.map(_._1)
new A(
  toto(x),
  toto(data.map(_._2)),
  toto[String](data.map(_._2))
)

// output:
// java.lang.String
// Any
// String
据我所知,似乎由于我的类
A
采用了“非类型化”(以及存在类型)序列,那么编译器在没有明确要求的情况下不会麻烦生成正确的类型标记(尽管它知道
data.map(u.\u 2)
的类型,它仍然使用
TypeTag[Any]
…)。但这看起来很奇怪,我想知道是否有更科学的解释来解释这一现象


另外,即使我不想创建特殊变量(如上面的
x
变量),我如何强制编译器生成正确的
TypeTag[String]
!我有一个解释,但我不确定它是否正确(比如说80%)

与Scala类型推断问题一样,您需要了解预期的类型。在这种情况下,
new A
的所有参数都使用预期的类型
Seq[\u]
,由于协方差的原因,这与
Seq[Any]
相同。因此:

  • toto(data.map(u._2))
    是按预期类型键入的
    Seq[Any]
    <代码>数据。映射(u._2)是按预期类型键入的
    Seq[Any]
    Seq#map
    的签名为

    def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Seq[A], B, That]): That 
    
    因此,根据预期类型推断出
    ,并找到合适的隐式
    bf
    。实际上,我不确定
    B
    是否被推断为
    String
    Any
    ,但这可能并不重要

  • val x=data.map(u.\u 1)
    中,没有预期的类型,因此
    B
    被推断为
    字符串
    ,根据
    A
    B
    找到隐式
    bf
    ,然后
    bf
    的完整类型推断出

  • toto(x)
    是按预期类型键入的
    Seq[Any]
    x
    是使用预期的类型
    Seq[Any]
    键入的,但它已经有了类型
    Seq[String]
    ,预期的类型并不重要


  • 我想通过可能的解决方案来扩展@AlexeyRomanov的答案,即如何强制编译器计算特定类型:

    根据我的想法,强制类型差异:

    sealed class =!=[A,B]
    trait LowerPriorityImplicits {
      implicit def equal[A]: =!=[A, A] = sys.error("should not be called")
    }
    object =!= extends LowerPriorityImplicits {
      implicit def nequal[A,B](implicit same: A =:= B = null): =!=[A,B] =
        if (same != null) sys.error("should not be called explicitly with same type")
        else new =!=[A,B]
    }
    
    现在我们可以将参数限制添加到
    toto

    class A(s: Seq[_]*)
    
    def toto[T: TypeTag](p: Seq[T])(implicit guard: T =!= Any): Seq[T] = {
      println(typeTag[T].tpe)
      p
    }
    
    val data = Seq(("a", "a"))
    val x = data.map(_._1)
    
    new A(
      toto(x),
      toto(data.map(_._2)),
      toto[String](data.map(_._2))
    )
    
    还有我的产量

    java.lang.String
    java.lang.String
    String
    

    toto[String](data.map(u.2))
    强制它使用
    TypeTag[String]
    。顺便说一句:在2.12.4中也发生了同样的情况。是的,它确实发生了,尽管在编译器知道信息的情况下指定它有点奇怪……很好的答案,不幸的是,如果我们确实需要
    Any
    ,例如使用
    toto(Seq(“1”,2))
    ,它会失败(在编译时)。我不想把<代码>任何< /代码>看作一个显式的错误,只是当它不是预期的类型时避免它。我会尝试使用你的代码,看看我是否能用它解决一些问题。Thanks@Vince.BdnWith=!=我破坏了任何预期类型检查的正确性。我不确定,您是否可以通过泛化函数来解决它(使用Any确定的情况将强制转换为
    Any
    ,而不是具体的类)。但是有了一个类的限制,您就可以为这个特定的案例引入唯一的附加方法,而不是在一堆案例中遇到问题。但是如果您能找到泛化的解决方案,我会很高兴的。谢谢,这确实是有意义的,但是我不太明白为什么它在使用
    data.map(u.\u 2.asInstanceOf[String])
    时也会失败。在这种情况下,
    。\u 2
    是用
    (String,String)=>String
    强制输入的。所以它应该回到你的2。解释一下,不是吗?因为键入是显式的,预期的类型可能会被忘记?我想这可能是因为您确实有两个参数,第二个参数是隐式的
    TypeTag[Class]
    ,其中
    Class
    是基于预期的
    Any
    解析的。因此,以后对基于
    map
    inners的
    Seq
    类型的评估不会影响整个类型
    T
    更重要的是
    map
    有两个类型参数。我已经编辑了答案。(虽然
    .\u 2.asInstanceOf[String]
    不应该按照以前的版本工作,
    (\u 2):((String,String))=>String
    应该而且仍然不应该。)