Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.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 如何从投影类型推断正确的类型参数?_Scala_Polymorphism_Type Inference_Type Projection - Fatal编程技术网

Scala 如何从投影类型推断正确的类型参数?

Scala 如何从投影类型推断正确的类型参数?,scala,polymorphism,type-inference,type-projection,Scala,Polymorphism,Type Inference,Type Projection,让Scala从类型投影推断正确的类型时,我遇到了一些麻烦 考虑以下几点: trait Foo { type X } trait Bar extends Foo { type X = String } def baz[F <: Foo](x: F#X): Unit = ??? 但以下内容无法编译: val x: Bar#X = ??? baz(x) Scala看到了x的“底层类型字符串”,但丢失了x是条的信息。如果我对类型进行注释,效果很好: baz[Bar](x)

让Scala从类型投影推断正确的类型时,我遇到了一些麻烦

考虑以下几点:

trait Foo {
  type X
}

trait Bar extends Foo {
  type X = String
}

def baz[F <: Foo](x: F#X): Unit = ???
但以下内容无法编译:

val x: Bar#X = ???    
baz(x)
Scala看到了
x
的“底层类型字符串”,但丢失了
x
条的信息。如果我对类型进行注释,效果很好:

baz[Bar](x)
有没有办法让Scala为
baz
推断正确的类型参数?
如果没有,一般的答案是什么使它不可能呢?

您也可以:

trait Foo{
X型
}
特征条扩展了Foo{
类型X=字符串
}
类BarImpl扩展了Bar{
def getX:X=“嗨”
}

def baz[F程序通过在上下文中添加此隐式转换进行编译:

implicit def f(x: Bar#X): Foo#X = x

因为这种隐式转换对于任何
F都是正确的,不是答案,但值得注意的是,如果您使用类型指示符而不是类型投影键入
x
,它可以工作,包括例如
对象栏扩展栏;val x:BAR.x=“a”baz(x)
。同样值得注意的是:您可以说服编译器,您确实希望
x
被键入或多或少类似于
Bar#x
,对于某些{val b:Bar}=“a”:b.x对于某些{val b:Bar}来说,其异常丑陋
val x:b.x
。看起来像是奇怪的用例。你为什么要这样做?@Jespernodenberg该用例来自于。如果我直接使用
RDF
特征的子类型,那么我无法从许多隐式函数中受益,比如。是的,编译器只看到
字符串
,并松开
Foo
上下文,尽管注释了ty使用
Bar#X
而不是
String
。到目前为止,我唯一的解决方案是总是抽象
Foo
,并在最后提供
Bar
。但这对我来说确实是个问题,因为它限制了我可以做的
baz
。(在我的情况下,
baz
也是一个隐式的)对。你可以这样想:类型X是Foo的成员,有点像Java中的其他静态vs成员变量。在没有实例的情况下尝试访问它就像在没有实例的情况下尝试访问成员变量。在:
trait HasType{type X}class Foo(val t:HasType){type a=t.X}
。可以有许多具有不同
A
Foo
,每个Foo都取决于传递的特定
t
HasType
的实例)。类型是动态的,因此必须以某种方式指定。这里的示例中的Foo#A不会告诉您或编译器更多关于
A
,而Person.age会告诉您Person实例的年龄。实例
t
提供类型信息。也许您可以静态地(在scala中,这意味着使用伴生对象)执行某些操作?对象Foo{type X=String}类Foo;val s:Foo.X=“hi”
test.scala:22: error: inferred type arguments [Nothing,java.lang.String] do not conform to method baz2's type parameter bounds [F <: this.Foo,T <: F#X]
baz2(x)
^
one error found
def baz3[F<: Foo](x : F#X) = {println("baz3 worked!")}
baz3[Bar]("hi")
implicit def f(x: Bar#X): Foo#X = x