5

Nói rằng tôi có một phương pháp có thể biến một (chức năng trên hai yếu tố) vào một (chức năng trên hai trình tự):Loại suy luận về chức năng ẩn danh với phong phú thêm-my-thư viện

def seqed[T](f: (T,T) => T): (Seq[T], Seq[T]) => Seq[T] = (_,_).zipped map f 

Nói cách, chức năng kết quả mất hai chuỗi xsys, và tạo ra một chuỗi mới gồm (xs(0) f ys(0), xs(1) f ys(1), ...) vì vậy, ví dụ, nếu xssSeq(Seq(1,2),Seq(3,4))f(a: Int, b: Int) => a + b, chúng ta có thể gọi nó như vậy:

xss reduceLeft seqed(f)   // Seq(4, 6) 

hoặc với một chức năng ẩn danh:

xss reduceLeft seqed[Int](_+_) 

này là khá tốt; nó sẽ là tốt đẹp để loại bỏ các đối số loại [Int] nhưng tôi không thấy làm thế nào (bất kỳ ý tưởng?).

Để làm cho nó cảm thấy một chút giống như phương pháp tupled, tôi cũng đã cố gắng mô hình phong phú thêm-my-thư viện:

class SeqFunction[T](f: (T,T) => T) { 
    def seqed: (Seq[T], Seq[T]) => Seq[T] = (_,_).zipped map f 
} 
implicit def seqFunction[T](f: (T,T) => T) = new SeqFunction(f) 

Đối với một chức năng được xác định trước điều này làm việc tuyệt vời, nhưng nó xấu xí với những người ẩn danh

xss reduceLeft f.seqed 
xss reduceLeft ((_:Int) + (_:Int)).seqed 

có một cách khác để tôi có thể tái cấu trúc này để các loại được suy ra, và tôi có thể sử dụng cái gì cú pháp như sau:

// pseudocode 
xss reduceLeft (_+_).seqed   // ... or failing that 
xss reduceLeft (_+_).seqed[Int] 

? Hay tôi hỏi quá nhiều suy luận kiểu?

+2

[Ở đây] (http://screencasts.chariotsolutions.com/uncovering-the-unknown-principles-of-type-inference-) Daniel Spiewak đã trình bày về các loại hệ thống và kiểu suy luận trong 'scala' và tĩnh khác ngôn ngữ đã nhập. Có lẽ đó không phải là chính xác về chủ đề, nhưng dù sao, tôi thấy nó cực kỳ thú vị. – 4e6

Trả lời

0

Lý do tại sao một loại chú thích là cần thiết trong

xss reduceLeft seqed[Int](_+_) 

nhưng không phải trong

xs zip ys map Function.tupled(_+_) 

là do sự khác biệt trong các yêu cầu loại giữa mapreduceLeft.

def reduceLeft [B >: A] (f: (B, A) ⇒ B): B 
def map  [B]  (f: (A) ⇒ B): Seq[B] // simple version! 

reduceLeft hy vọng seqed trở lại loại B nơi B >: Int. Có vẻ như do đó, loại chính xác cho seqed không thể được biết, vì vậy chúng tôi phải cung cấp chú thích. Thông tin thêm trong this question.

Một cách để khắc phục điều này là triển khai lại reduceLeft mà không có giới hạn dưới.

implicit def withReduceL[T](xs: Seq[T]) = new { 
    def reduceL(f: (T, T) => T) = xs reduceLeft f 
} 

Test:

scala> Seq(Seq(1,2,3), Seq(2,2,2)) reduceL seqed(_+_) 
res1: Seq[Int] = List(3, 4, 5) 

Vấn đề bây giờ là điều này bây giờ không hoạt động trên vùng phụ của Seq (ví dụ List), có hoặc không có tham số [Int]:

scala> Seq(List(1,2,3), List(2,2,2)) reduceL seqed(_+_) 
<console>:11: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2)) 
       Seq(List(1,2,3), List(2,2,2)) reduceL seqed(_+_) 
                 ^

reduceL mong đợi một chức năng của loại (List[Int], List[Int]) => List[Int]. Vì Function2 được định nghĩa là Function2 [-T1, -T2, +R], (Seq[Int], Seq[Int]) => Seq[Int] không phải là sự thay thế hợp lệ.

4

Tôi chắc chắn bạn hỏi quá nhiều. Nhập suy luận trong Scala goes from left to right, do đó, loại số (_+_) cần phải được tìm ra đầu tiên trước khi xem xét phần .sedeq. Và không có đủ thông tin ở đó.

5

Bạn không thể thực hiện theo cách mình muốn, nhưng hãy xem Function.tupled, là bộ phận đối kháng với số .tupled giải quyết vấn đề này.

scala> List(1, 2, 3) zip List(1, 2, 3) map (_ + _).tupled 
<console>:8: error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2)) 
       List(1, 2, 3) zip List(1, 2, 3) map (_ + _).tupled 
               ^
<console>:8: error: missing parameter type for expanded function ((x$1: <error>, x$2) => x$1.$plus(x$2)) 
       List(1, 2, 3) zip List(1, 2, 3) map (_ + _).tupled 
                ^

scala> List(1, 2, 3) zip List(1, 2, 3) map Function.tupled(_ + _) 
res7: List[Int] = List(2, 4, 6) 
+0

Chữ ký của 'Function.tupled' là' def tupled [a1, a2, b] (f: (a1, a2) => b): Tuple2 [a1, a2] => b'. Những gì tôi không thể làm việc như thế nào nó biết các loại tham số trong ví dụ trên, trong khi phương pháp của tôi yêu cầu '[Int]' trong 'xss reduceLeft seqed [Int] (_ + _)'. –

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