如何用中间类型键入特征来链接计算?



我想有一个特征,有两种方法如下:

trait Foo[A] {
def bar1(): A
def bar2(a: A): Unit
}

现在的问题是,我不希望 A 传播。说:

val foos: List[Foo[???]] = ...
foos.foreach({ foo =>
val x = foo.bar1()
// stuff
foo.bar2(x)
})

在此代码中,类型 A 并不重要,但我无法让编译器相处融洽。

x的类型是动态的,这是我可能需要消除的东西吗?

有没有重写这种代码的模式?

Let

val foos: List[Foo[_]] = ???

这与

val foos: List[Foo[T] forSome { type T }] = ???

这使foos成为对的列表。每对由一个类型T和一个类型Foo[T]的值组成。在foreach中,解构该对以获取对该类型的访问权限并命名它,并获取值:

foos.foreach { case foo: Foo[t] =>
val x = foo.bar1() // inferred type t
foo.bar2(x) // foo.bar2 wants a t, x is a t, this is well-formed
}

斯卡斯蒂

注意:"对"在类型擦除后消失。在擦除的代码中,List仅包含Foo对象。有必要用case显式解构该对。如果你不这样做,那么foo将引用整个对,并且在每次使用时,编译器将隐式解构它。发生这种情况时,所包含类型的两个外观不被视为相等。

foos.foreach { foo =>
val x = foo.bar1()
foo.bar2(x)
}

foos.foreach { foo =>
val x = foo match { case foo0: Foo[t] => foo0.bar1() }
foo match { case foo0: Foo[u] => foo0.bar2(x) }
}

编译器看不到tu实际上是相同的。这是因为定义xt不在范围内,因此您最终会得到x: Any,因此您丢失了类型信息。

尽管存在类型,这将在未来的 Scala 中工作(使用_语法(。

你的意思是没关系?这很重要,而且很重要!

看看这个:

val x = foo.bar1()
// stuff
foo.bar2(x)

在这里,您需要确保x的类型与foo.bar2需要的类型相同。

您可能可以执行以下操作:

def process[A](data: List[Foo[A]]): Unit = 
list.foreach { foo =>
val x = foo.bar1()
// stuff
foo.bar2(x)
}

但也许,你想用"动态">说的是你想要一个不同类型的Foo列表。因此,哪一个并不重要,因为您知道每个 foo 都会生成一个它可以使用的值,如果是这样,您可以使用类型成员而不是类型参数

trait Foo {
type A
def bar1(): A
def bar2(a: A): Unit
}
def process(data: List[Foo]): Unit = 
list.foreach { foo =>
val x = foo.bar1()
// stuff
foo.bar2(x)
}

最新更新