2010-07-08 9 views
8

Sto cercando di scrivere un interpolate metodo generico che funziona su qualsiasi tipo che ha due metodi, un * e +, come questo:Scala: come definire un tipo strutturale che si riferisce a se stesso?

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 
} 

Questo non funziona se (sulla Scala 2.8.0 .RC7), ricevo i seguenti messaggi di errore:

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

Come si specifica il tipo di struttura in modo corretto? (O c'è un modo migliore per farlo?)

+0

http://www.scala-notes.org/2010/06/avoid-structural-types-when-pimping-libraries/ potrebbe aiutare qui – VonC

+0

@VonC grazie ... questo è il mio blog! ;-) – Jesper

+0

"© 2010 Jesper de Jong" ... riiiight. Bene, mi dispiace per quello;) – VonC

risposta

8

Sicuramente si potrebbe risolvere questo problema utilizzando il typeclasses approccio (ad esempio di 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 

Poi, ovviamente, si avrebbe bisogno di un (implicito) typeclass conversione portata per tutti i tipi che si preoccupava:

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

Allora questo può essere eseguito con facilità:

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

    println(j) //prints 6 
} 
+0

Approccio interessante, ma produce un errore del compilatore: http://gist.github.com/471620 – Jesper

+0

Spiacente: al momento non ho accesso a un REPL funzionante. L'approccio funzionerà, probabilmente solo alcuni spigoli da risolvere! –

+0

Sembra che il problema abbia a che fare con i due termini 'a * (1.0 - t)' e 'b * t' entrambi che producono un' X' e quindi stai facendo 'X + X' invece di' Interpolable [X ] + Interpolable [X] ', l'implicito non viene chiamato per' + 'per qualche motivo. – Jesper

3

AFAIK, questo non è possibile. Questo era uno dei miei first questions.

+1

Davvero? Questo mi sorprende, Scala ha un sistema di tipi così potente, ma non è possibile. Grazie. – Jesper

+0

@Jesper Penso di aver letto che c'è un problema di divergenza di tipo relativo al supporto di ciò. –

Problemi correlati