2011-07-31 22 views
12

Khi tôi cố gắng biên dịch ví dụ nhỏ:Loại suy ra để có gì trong Scala

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) 
} 

tôi nhận được lỗi:

[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) 

Rõ ràng, cơ chế suy luận kiểu không có khả năng suy ra A và B ngoài Bar [A, B]. Tuy nhiên, nó hoạt động nếu tôi vượt qua tất cả các loại bằng tay:

val y = Helper.callFoo[Int,Double,Bar[Int,Double]](x) 

Tôi có cách nào để tránh loại bỏ một cách rõ ràng?

Trả lời

11

Bạn sẽ phải thay đổi chữ ký của callFoo này:

def callFoo[A, B, FF[A, B] <: Foo[A, B]](f: FF[A, B]): FF[A, B]#F[A, B] = 

Bạn phải nói với trình biên dịch rằng FF thực sự là một loại parametrized.

+0

@Kipton_Barros: Vâng, tôi đã chọn Jean-Phillipe chỉ trả lời vì nó ngụ ý ít được tái cấu trúc với cơ sở mã hiện tại của tôi. – paradigmatic

+0

@paradigmatic Vâng, câu trả lời của Jean-Philippe khá hay. Tôi thấy nó thú vị rằng mặc dù tham số 'FF' không phải là loại cao hơn, làm cho nó giúp suy luận. Tôi đã thử kỹ thuật của Jean-Philippe về một câu hỏi liên quan, nhưng không thể làm cho nó hoạt động cho đến nay: http://stackoverflow.com/questions/6892781/why-doesnt-scala-fully-infer-type-parameters-when- type-parameters-are-lồng nhau/6893057 # 6893057 –

2

Nó có hoạt động để sử dụng loại thành viên thay vì thông số?

trait Foo { 
    type A 
    type B 
    type F 
    def foo(): F 
} 

class Bar extends Foo { 
    type F = Bar 
    def foo() = this 
} 

object Helper { 
    def callFoo[FF <: Foo](f: FF): FF#F = 
    f.foo() 
} 

object Run extends App { 
    val x = new Bar{type A=Int; type B=Double} 
    val y = Helper.callFoo(x) 
    println(y.getClass) 
} 

Khi sử dụng các thành viên loại, nó là hữu ích để biết rằng họ có thể nổi lên như các tham số kiểu sử dụng tinh tế, như trong câu trả lời Miles Sabin để: Why is this cyclic reference with a type projection illegal?

Xem thêm những câu hỏi gần đây này, mà dường như giống như của bạn : Scala fails to infer the right type arguments

Các vấn đề liên quan