什么是Scala中的类型投影有用?为什么Scala的类型系统支持类型投影和路径依赖类型?这个设计决定背后的理由是什么?
以下伪Scala产生"非法循环引用"错误:
trait GenT[A]
trait T extends GenT[T#A] {
type A
}
Run Code Online (Sandbox Code Playgroud)
问题:为什么这是非法的?是否存在稳健性的基本问题,或者它是Scala类型系统的限制?有解决方法吗?
我的目的是创建一个T具有类型成员的特征,该特征A可以通过超级特征按需提升到类型参数GenT[A].例如,一个应用程序可能是约束的表达
def foo[A, S1 <: GenT[A], S2 <: GenT[A]] ...
Run Code Online (Sandbox Code Playgroud)
这可以像使用def foo[S1 <: T, S2 <:T] ...约束那样使用S1#A == S2#A.
如果技术可行,它也可能有助于解决这个问题:如何专注于Scala中的类型投影?
注意:我可以使用GenT而不是在T任何地方,但我试图避免这种情况,因为它会导致许多类型参数在我的所有代码中传播"感染".
下面的两个问题看似相似,但是关于不同类型的循环引用:
当我尝试编译小例子时:
trait Foo[A,B] {
type F[_,_]
def foo(): F[A,B]
}
class Bar[A,B] extends Foo[A,B] {
type F[D,E] = Bar[D,E]
def foo() = this
}
object Helper {
def callFoo[A,B,FF <: Foo[A,B]]( f: FF ): FF#F[A,B] =
f.foo()
}
object Run extends App {
val x = new Bar[Int,Double]
val y = Helper.callFoo(x)
println( y.getClass )
}
Run Code Online (Sandbox Code Playgroud)
我收到错误:
[error] src/Issue.scala:20: inferred type arguments
[Nothing,Nothing,issue.Bar[Int,Double]] do not conform to method callFoo's type
parameter bounds [A,B,FF <: issue.Foo[A,B]]
[error] val y = Helper.callFoo(x) …Run Code Online (Sandbox Code Playgroud) 背景信息:我目前正在尝试建立一个包含几种不同搜索算法的通用图形库(我已经开始使用Dijkstra).我已经设置了一些特征来表示在某些类型的图中可以找到的方法(例如加权,定向):
trait GraphOps[V,E] { ... }
trait WeightedGraphOps[V,E] extends GraphOps[V,E] { ... }
trait DirectedGraphOps[V,E] extends GraphOps[V,E] { ... }
object GraphOps{
def Dijkstra[V,E,G <: WeightedGraphOps[V,E] with DirectedGraphOps[V,E]](graph:G, start:V) = { ... }
}
Run Code Online (Sandbox Code Playgroud)
在其他地方,我有一个类作为加权有向图的具体实现,我想运行Dijkstra的算法:
class GraphMap[T](...)
extends scala.collection.mutable.Map[Position,T]
with WeightedGraphOps[Position,Edge] with DirectedGraphOps[Position,Edge] { ... }
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试测试它时:
val graph = new GraphMap[Int](...)
val (dist, prev) = GraphOps.Dijkstra(graph, Position(0,0))
Run Code Online (Sandbox Code Playgroud)
问题:我在编译过程中遇到以下错误:error: inferred type arguments [com.dylan.data.Position,Nothing,com.dylan.data.GraphMap[Int]] do not conform to method Dijkstra's type parameter bounds [V,E,G <: com.dylan.data.WeightedGraphOps[V,E] with com.dylan.data.DirectedGraphOps[V,E]] …
Scala 3 将在类型推断方面带来哪些变化?当前文档只是说明TODO。例如,
斯卡拉 2.13
scala> val i: Int = 42
val i: Int = 42
scala> val c: Char = 'a'
val c: Char = a
scala> List(i,c)
val res0: List[Int] = List(42, 97)
Run Code Online (Sandbox Code Playgroud)
Scala 3 (dotty 0.24.0-RC1)
scala> val i: Int = 42
val i: Int = 42
scala> val c: Char = 'a'
val c: Char = a
scala> List(i,c)
val res0: List[AnyVal] = List(42, a)
Run Code Online (Sandbox Code Playgroud)
斯卡拉 2.13
scala> 42 == Some(42) …Run Code Online (Sandbox Code Playgroud)