9

Tôi có một đoạn mã mà tôi không thể xử lý theo cách mình muốn. Tôi có một lớp được định nghĩa theo cách sau (rút gọn cho việc này):Nhiều loại đối số đóng tham số không được suy ra

class Behaviour[T](private val rule: Time => T) { 
    def map1[U, V](behaviour: Behaviour[U], func: (T, U) => V): Behaviour[V] = { 
    new Behaviour(time => func(this.at(time), behaviour.at(time))) 
    } 
} 

Khi chơi xung quanh với lớp học này tôi đã cố gắng một cái gì đó mà tôi nghĩ sẽ là tầm thường:

val beh = Behaviour(time => 5) 
val beh2 = Behaviour(time => 5) 
beh.map1(beh2, (a, b) => a + b) 

Đối với người cuối cùng dòng Tôi nhận được lỗi sau:

<console>:13: error: missing parameter type 
      beh.map1(beh2, (a, b) => a + b) 
          ^

Tôi có thể chỉ định loại tham số đóng và hoạt động chính xác nhưng tại sao không gõ suy luận ở đây? Tất nhiên tôi cũng có thể chỉ định các loại chung cho hàm (xem bên dưới cho cả hai giải pháp).

Tôi nghĩ Scala đã thực hiện 'quét' để suy ra các loại và sẽ thấy beh2 và được chuyển vào hàm và giả định U ở đây là Int. Có cách nào tôi có thể sửa lỗi này mà không xác định các loại tham số đầu vào (cho đóng cửa hoặc generics)?

EDIT: Ví dụ về hai bản vá Tôi có:

beh.map1[Int, Int](beh2, (a, b) => a + b) 
beh.map1(beh2, (a, b : Int) => a + b) 

Trả lời

19

Xem this scala-debate thread để thảo luận về những gì đang xảy ra ở đây. Vấn đề là suy luận kiểu của Scala xảy ra trên mỗi danh sách tham số , không theo thông số .

Như Josh Suereth ghi chú trong chủ đề đó, có một lý do chính đáng cho cách tiếp cận hiện tại. Nếu Scala có suy luận kiểu tham số cho mỗi tham số, trình biên dịch không thể suy ra một giới hạn trên trên các kiểu trong cùng một danh sách tham số. Hãy xem xét những điều sau đây:

trait X 
class Y extends X 
class Z extends X 

val y = new Y 
val z = new Z 

def f[A](a: A, b: A): (A, A) = (a, b) 
def g[A](a: A)(b: A): (A, A) = (a, b) 

f(y, z) hoạt động chính xác như chúng ta mong đợi, nhưng g(y)(z) đưa ra một loại không phù hợp, vì vào thời điểm trình biên dịch được vào danh sách đối số thứ hai nó đã được chọn Y như các loại cho A.

4

Một trong những cách để sửa lỗi này là để xác định nhiều danh sách đối số. Vì vậy, phương pháp map1 của bạn sẽ được xác định như thế này:

def map1[U, V](behaviour: Behaviour[U])(func: (T, U) => V): Behaviour[V] = ... 

và bạn có thể sử dụng nó như thế này:

beh.map1(beh2)((a, b) => a + b) 
beh.map1(beh2)(_ + _) 

Tôi không hoàn toàn chắc chắn lý do tại sao suy luận kiểu không hoạt động trong trường hợp của bạn, nhưng tôi tin rằng nó có liên quan đến việc sử dụng thông số loại U. Bạn đang sử dụng nó hai lần - cho đối số đầu tiên và thứ hai. Nó có thể quá phức tạp cho trình biên dịch để tìm ra. Trong trường hợp có 2 danh sách đối số, U sẽ được suy ra trong quá trình biên dịch danh sách đối số đầu tiên và danh sách đối số thứ hai sẽ sử dụng loại đã suy luận.

+0

Cảm ơn rất nhiều công trình tốt! Tôi sẽ chấp nhận câu trả lời nếu không ai có thể đi kèm với một lời giải thích cho những gì đang xảy ra trong ngày hôm sau. – seadowg

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