2010-06-15 2 views
8

Tôi cần kiểm tra lại (vui lòng).Làm thế nào để chuyên đối số tham số kiểu cho nhiều loại khác nhau cho trong Scala?

Trong một bài viết (http://www.win-vector.com/blog/2010/06/automatic-differentiation-with-scala/) Tôi vừa viết tôi đã nói rằng đó là niềm tin của tôi trong Scala rằng bạn không thể chỉ định một hàm nhận một đối số mà chính nó là một hàm có tham số kiểu không ràng buộc. Tôi đã chỉnh sửa câu hỏi này để thử và đơn giản hóa ví dụ.

Các mã sau hoạt động bằng cách giới thiệu một đặc điểm GenericFn mà bắt chước các đặc điểm Scala Function1, ngoại trừ nó có một tham số tự do gõ vào chức năng:

object TypeExample { 
    trait NumberBase { 
     def result:String 
    } 

    class A extends NumberBase { 
     def result = "A" 
    } 

    class B extends NumberBase { 
     def result = "B" 
    } 

    trait GenericFn { 
     def apply[X<:NumberBase](x:X):String 
    } 

    def specializeAndApplyTwice(f:GenericFn):String = { 
     f[A](new A()) + f[B](new B()) 
    } 

    def main(args : Array[String]) : Unit = { 
     val f = new GenericFn { 
      def apply[X<:NumberBase](x:X):String = { x.result } 
     } 
     println(specializeAndApplyTwice(f)) 
    } 
} 

này hoạt động, nhưng có một cách để làm điều này mà không có đặc tính GenericFn (sử dụng ký pháp hàm chuẩn)? Ví dụ đoạn code dưới đây không thành công với các lỗi thời gian biên dịch: "loại không phù hợp; tìm thấy: TypeExample2.A yêu cầu: _ $ 1 nơi loại _ $ 1 <: TypeExample2.NumberBase":

def specializeAndApplyTwice(f:(_<:NumberBase)=>String):String = { 
    f(new A()) + f(new B()) 
} 
+0

Ví dụ của bạn có thể là: def g (f: Array [Double] => Double, x: Array [Double]): Double –

+0

... và có lẽ, exampe thứ hai phải là def g (f [Y] : Mảng [Y] => Y, x: Mảng [Y]): Y? Nếu không, bạn có thể viết def g (f: Array [_] => Double, x: Array [Double]): Double, nhưng tôi cho rằng đây không phải là thứ bạn muốn. –

+0

Arjan, thực ra các ví dụ của tôi gần hơn với những gì tôi muốn. Trong mã thực tế của tôi Y có một ràng buộc kiểu (mà tôi không tái tạo ở đây) của biểu mẫu Y <: NumberBase [Y] và NumberBase [Y] khai báo các phương thức để chuyển đổi và từ Y và Doubles. g() sử dụng cấu trúc này để chuyển đổi lên từ máy Doubles thành Ys, làm một số công việc và sau đó chuyển đổi xuống thành Doubles (vì vậy mã bên ngoài không chọn kiểu của Y và không cần xử lý kiểu của Y). – jmount

Trả lời

2

tái khẳng định động lực ban đầu cho câu hỏi: Chúng tôi muốn cung cấp một loại cho một giá trị 'g' bởi vì chúng tôi muốn chuyển nó qua. Giá trị Scala (tất nhiên) không thể có loại đa hình, ngay cả khi chúng là giá trị hàm. Vì vậy, làm thế nào để cung cấp cho một loại mà một số phần của nó là không rõ?

Vì vậy, tôi tin rằng một giải pháp là sử dụng ký tự đại diện (một hình thức trừu tượng hiện sinh):


    def g(f: Array[_ <: NumberBase[_]] => Double, z: Array[Double]): Double 

Các văn xuôi giải thích cho các loại g là: một chức năng từ Array [T] và Array [đúp] thành Double, trong đó T là một số loại mở rộng gấp đôi. "một số" là từ chỉ ra trừu tượng tồn tại, chúng tôi yêu cầu loại đó tồn tại mặc dù chúng tôi không quan tâm vào thời điểm này mà nó là một.

+0

Tôi đã chỉnh sửa rất nhiều câu hỏi để thử và đánh dấu ví dụ của bạn. Tôi không thể làm cho nó hoạt động- nhưng rõ ràng đó có thể là lỗi của tôi (tôi không biết nhiều về các ký hiệu _ khác nhau). – jmount

+0

Trong câu hỏi được cải cách, có vẻ như đơn giản hơn khi sử dụng ... Tôi tin rằng có thêm khó khăn trong công thức ban đầu vì cần thiết sử dụng tham số kiểu (hoặc loại ký tự đại diện _) để tạo kiểu mảng. BTW cho đầy đủ: chức năng từ các loại đến các giá trị được biết đến trong lý thuyết (phép tính được gọi là F-omega) nhưng Scala không có chúng ở dạng tinh khiết của chúng. Sẽ cần một VM phù hợp. _ trong các loại luôn có nghĩa là loại ký tự đại diện. Có thể bạn thấy trang này hữu ích, nó có một số ví dụ http://www.scala-lang.org/node/43 – buraq