我在依赖路径的类型上遇到了一些问题。
我有一些Foo
带有抽象类型成员的类型F
。诸如的实例Bar
将提供具体类型。
然后是一个类型类Baz
。对于每种的具体类型,我都有类型类的实例Foo#F
(但Foo
本身没有)。
这是一个例子:
sealed trait Foo {
type F
}
object Bar extends Foo {
type F = Array[Byte]
}
trait Baz[B] {
def b(b: B): String
}
object Baz {
implicit val bazByteArray: Baz[Array[Byte]] = (b: Array[Byte]) => new String(b)
}
我无法编译它:
def f(a: Foo): Baz[a.F] = {
val baz = a match {
case bar@Bar => g(bar)
}
baz
} // Expression of type Baz[(a.type with Bar.type)#F] doesn't conform to Baz[a.F]
val x2: Foo = Bar
val y2: Baz[x2.F] = f(x2) // Expression of type Baz[Foo#F] doesn't conform to expected type Baz[x2.F]
这样可以编译:
def g(a: Foo)(implicit baz: Baz[a.F]): Baz[a.F] = {
baz
}
val x1: Bar.type = Bar
val y1: Baz[x1.F] = f(x1)
为什么g
编译却不编译f
?类型不一样吗?
我该如何f
编译?我需要补充一些证据吗?
似乎有点类似于这个问题。这是一种使其编译的方法:
sealed trait Foo {
type F
def asSingleton: FooSingleton[F]
}
trait FooSingleton[X] extends Foo {
type F = X
def asSingleton: FooSingleton[X] = this
}
object Bar extends FooSingleton[Array[Byte]]
trait Baz[B] {
def b(b: B): String
}
object Baz {
implicit val bazByteArray: Baz[Array[Byte]] =
(b: Array[Byte]) => new String(b)
}
def g(a: Foo)(implicit baz: Baz[a.F]): Baz[a.F] = {
baz
}
val x1: Bar.type = Bar
val y1: Baz[x1.F] = f(x1)
def f[T](a: Foo { type F = T } ): Baz[T] = {
(a.asSingleton: FooSingleton[T]) match {
case bar @ Bar => g(bar)
}
}
val x2: Foo = Bar
val y2: Baz[x2.F] = f(x2)
您进行g
编译,因为baz
type的依赖于路径的参数Baz[a.F]
来自外部,因此编译器会插入一个具体的隐式实例,并且a
内部的任何地方都不会使用实际值g
。
您f
不会编译,因为只会B[a.F]
出现在返回类型中,并且在将实际参数传递给之前无法使其更加具体。a
f
从某种意义上说,f
中断会破坏参数a
和返回值之间的路径,因为它会导致以下“不连续跳转”:
a: Foo
a
到Bar
单(通过模式匹配)g
从混凝土Bar
单例到混凝土Baz[Array[Byte]]
Baz[Array[Byte]]
,似乎不再与之相关Baz[a.F]
。可以通过证明不连续的“跳转”确实只是一条始终保持在同一位置的标识路径来修复此路径,因此它实际上不会在任何地方移动,因此a.F
和推断的类型相同,即T
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句