2010-07-08 12 views
8

Tôi đang cố gắng để viết một interpolate phương pháp chung mà hoạt động trên bất kỳ loại có hai phương pháp, một *+, như thế này:Scala - làm thế nào để xác định một loại cấu trúc đề cập đến chính nó?

trait Container { 
    type V = { 
    def *(t: Double): V 
    def +(v: V): V 
    } 

    def interpolate(t: Double, a: V, b: V): V = a * (1.0 - t) + b * t 
} 

này không hoạt động mặc dù (trên Scala 2.8.0 .RC7), tôi nhận được thông báo lỗi sau:

<console>:8: error: recursive method + needs result type 
      def +(v: V): V 
         ^
<console>:7: error: recursive method * needs result type 
      def *(t: Double): V 
          ^

Làm cách nào để chỉ định loại cấu trúc chính xác? (Hoặc có cách nào tốt hơn để thực hiện việc này không?)

+0

http://www.scala-notes.org/2010/06/avoid-structural-types-when-pimping-libraries/ có thể giúp ở đây – VonC

+0

@VonC cảm ơn ... đó là blog của riêng tôi! ;-) – Jesper

+0

"© 2010 Jesper de Jong" ... riiiight. Vâng, xin lỗi về điều đó;) – VonC

Trả lời

8

Chắc chắn bạn có thể giải quyết vấn đề này bằng cách sử dụng typeclasses cách tiếp cận (các ví dụ Scalaz):

trait Multipliable[X] { 
    def *(d : Double) : X 
} 

trait Addable[X] { 
    def +(x : X) : X 
} 

trait Interpolable[X] extends Multipliable[X] with Addable[X] 

def interpolate[X <% Interpolable[X]](t : Double, a : X, b : X) 
    = a * (1.0 - t) + b * t 

Sau đó, rõ ràng bạn sẽ cần một (implicit) typeclass chuyển đổi trong phạm vi cho tất cả các loại bạn quan tâm:

implicit def int2interpolable(i : Int) = new Interpolable[Int] { 
    def *(t : Double) = (i * t).toInt 
    def +(j : Int) = i + j 
} 

Sau đó, điều này có thể được chạy một cách dễ dàng:

def main(args: Array[String]) { 
    import Interpolable._ 
    val i = 2 
    val j : Int = interpolate(i, 4, 5) 

    println(j) //prints 6 
} 
+0

Cách tiếp cận thú vị, nhưng nó tạo ra lỗi trình biên dịch: http://gist.github.com/471620 – Jesper

+0

Rất tiếc - Tôi không có quyền truy cập vào REPL đang hoạt động vào lúc này. Cách tiếp cận này sẽ hoạt động, có lẽ chỉ là một vài cạnh thô để sắp xếp! –

+0

Có vẻ như vấn đề phải làm với hai thuật ngữ 'a * (1.0 - t)' và 'b * t' cả hai tạo ra một' X' và sau đó bạn đang làm 'X + X' thay vì' Interpolable [X ] + Interpolable [X] ', ngầm định không được gọi cho' + 'vì lý do nào đó. – Jesper

3

AFAIK, điều này là không thể. Đây là một trong số first questions của riêng tôi.

+1

Thật sao? Điều đó làm tôi ngạc nhiên, Scala có một hệ thống kiểu mạnh mẽ như vậy, nhưng điều này là không thể. Cảm ơn. – Jesper

+0

@ Jesper Tôi nghĩ rằng tôi đã đọc có một vấn đề phân kỳ loại liên quan đến việc hỗ trợ điều đó. –