加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 类型变量的类型模式的用例和示例

发布时间:2020-12-16 09:10:18 所属栏目:安全 来源:网络整理
导读:我发现阅读规范 scala支持绑定类型变量做一个类型模式匹配: Map(1 - "one",2 - "two") match { case l: Map[k,v] = // binds k to Int and v to String // k and v are types as shown here: val i: Iterator[Tuple2[k,v]] = l.iterator println(i.mkString
我发现阅读规范 scala支持绑定类型变量做一个类型模式匹配:

Map(1 -> "one",2 -> "two") match {
  case l: Map[k,v] =>
    // binds k to Int and v to String
    // k and v are types as shown here:
    val i: Iterator[Tuple2[k,v]] = l.iterator
    println(i.mkString(","))
}

有没有什么花哨的事情或实际的事情我可以做到这一点?或绑定类型变量仅对类型文档目的有用吗?

对我来说,Scala有时候需要类型注释,例如定义函数,所以我试过:

def prepender(obj: Any) = obj match {
  case xs: List[a] => (x: a) => x :: xs
  case opt: Some[a] => (x: a) => x :: Nil
}

但是返回函数的类型是奇怪的:

prepender: (obj: Any)a with a => List[Any] forSome { type a; type a }

scala> val p = prepender(List(1,2))
p: a with a => List[Any] forSome { type a; type a } = <function1>

scala> p(1)
<console>:10: error: type mismatch;
 found   : Int(1)
 required: a(in value res7) with (some other)a(in value res7) where 
   type (some other)a(in value res7),type a(in value res7)

解决方法

我希望这不会太长,但是我真的很怀疑,这就是为什么我会先尝试提供一个快速的答案:“当你命名(抽象)某些东西时,主要的用例是在以后提及”.那现在没有帮助,是吗?

考虑这个简单的Scala功能:

val sum = (a: Int,b: Int) => a + b

编译器不需要知道a是a,b是b.所有它需要知道一个以及b是类型Int和一个来到b之前(在这种情况下,这是没有关系的,因为添加是可交换的,但编译器关心!). Scala提供了一个(不要误会我也喜欢它)编译器友好的占位符语法,作为这个“假设”的证明.

val sum: (Int,Int) => Int = _ + _ // where the 1st _ differs from the 2nd _

现在看看这个:

case x: SomeTypeParameterizedWith[AnotherType] // AnotherType is erased anyway
case x: SomeParameterizedType[_] // Existential type
case x: SomeParameterizedType[kind] // Existential type which you can reference

当您不关心类型参数时,请使用占位符语法.当你做(无论什么原因)时,请注意你应该用小写命名为type参数,以便编译器知道你想把它当作一个标识符.

回到你的问题

存在类型的主要用途是围绕Java的通配符类型.
这是从Programming in Scala – Existential Types年开始,并被你的真正的轻微修改.

// This is a Java class with wildcards
public class Wild {
  public java.util.Collection<?> contents() {
    java.util.Collection<String> stuff = new Vector<String>();
    stuff.add("a");
    stuff.add("b");
    stuff.add("see");
    return stuff;
  }
}

// This is the problem
import scala.collection.mutable.Set
val iter = (new Wild).contents.iterator
val set = Set.empty[???] // what type goes here?
while (iter.hasMore)
  set += iter.next()

// This is the solution
def javaSet2ScalaSet[T](jset: java.util.Collection[T]): Set[T] = {
  val sset = Set.empty[T] // now T can be named!
  val iter = jset.iterator
  while (iter.hasNext)
    sset += iter.next()
  sset
}

好的,那刚才发生了什么?简单的泛型,没有魔法吗?如果您是日常处理仿制药,这对您来说看起来是正常的,但您忘记了将范围引入范围的超级概念仅适用于类和方法.如果你在一个班级或一个方法之外,只是在无处不在的随机范围(如REPL)怎么办?或者如果你在一个类或一个方法,但是类型参数还没有被引入其范围呢?这是你的问题和这个答案来的地方.

val set = new Wild().contents match {
  case jset: java.util.Collection[kind] => {
    val sset = Set.empty[kind]
    val iter = jset.iterator
    while (iter.hasNext)
      sset += iter.next()
    sset
  }
}

标识符类型是必需的,因此编译器可以验证您是指同一件事.

注意,您不能只是将字符串添加到集合中,因为集合的类型为Set [_].

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读